2 Copyright 2005-2006 Mark Calderbank
3 Copyright 2020 Chris Tallon
5 This file is part of VOMP.
7 VOMP is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 VOMP is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with VOMP. If not, see <https://www.gnu.org/licenses/>.
42 void Stream::shutdown()
44 if (initted) free(outbuf);
49 int Stream::init(DrainTarget* tdt, int bufsize)
51 outbuf = static_cast<u1*>(malloc(bufsize));
53 if (!outbuf) return 0;
68 if (draintarget) draintarget->ResetTimeOffsets();
71 int Stream::put(const u1* inbuf, int len, u1 type, unsigned int index)
75 if (!draintarget) return 0;
77 MediaPacket newPacket;
78 newPacket.length = len;
79 newPacket.pos_buffer = 0;
80 newPacket.type = type;
83 newPacket.synched = false;
84 newPacket.index = index;
85 newPacket.disconti = false;
86 newPacket.presentation_time = 0;
88 if (type != MPTYPE_MPEG_AUDIO_LAYER3) //no PES
93 if ((inbuf[7] & 0x80) && len > 14 )
95 newPacket.synched = true;
96 newPacket.pts = ( static_cast<u8>(inbuf[9] & 0x0E) << 29 ) |
97 ( static_cast<u8>(inbuf[10]) << 22 ) |
98 ( static_cast<u8>(inbuf[11] & 0xFE) << 14 ) |
99 ( static_cast<u8>(inbuf[12]) << 7 ) |
100 ( static_cast<u8>(inbuf[13] & 0xFE) >> 1 );
102 if ((inbuf[7] & 0x40) && len > 19)
104 newPacket.dts = ( static_cast<u8>(inbuf[14] & 0x0E) << 29 ) |
105 ( static_cast<u8>(inbuf[15]) << 22 ) |
106 ( static_cast<u8>(inbuf[16] & 0xFE) << 14 ) |
107 ( static_cast<u8>(inbuf[17]) << 7 ) |
108 ( static_cast<u8>(inbuf[18] & 0xFE) >> 1 );
112 TELEM((localWhich ? 11 : 4), newPacket.pts);
113 TELEM((localWhich ? 12 : 5), newPacket.dts);
115 //ok we have the pts now convert it to a continously time code in 100ns units
116 if (hasdts && draintarget->dtsTimefix()) newPacket.presentation_time = static_cast<u8>(newPacket.dts * 10000LL / 90LL); // Windows only
117 else newPacket.presentation_time = static_cast<u8>(newPacket.pts * 10000LL / 90LL);
119 TELEM((localWhich ? 13 : 6), newPacket.presentation_time);
121 // now PTS & DTS are original, presentation_time is OMX ticks. If it's rolled, it's rolled!
123 //newPacket.presentation_time-=draintarget->SetStartOffset(static_cast<u8>(newPacket.pts*10000LL/90LL),&newPacket.disconti);
124 //newPacket.presentation_time -= draintarget->SetStartOffset(static_cast<u8>(newPacket.pts * 10000LL / 90LL), &newPacket.disconti);
125 long long returnedStartOffset = draintarget->SetStartOffset(static_cast<u8>(newPacket.pts * 10000LL / 90LL), &newPacket.disconti);
126 newPacket.presentation_time -= returnedStartOffset;
127 //LogNT::getInstance()->debug("MP", "draintarget {} PTSmod {} disconti {} rso: {}", (void*)draintarget, newPacket.presentation_time, newPacket.disconti, returnedStartOffset);
129 TELEM((localWhich ? 14 : 7), newPacket.presentation_time);
130 TELEM((localWhich ? 15 : 8), returnedStartOffset);
137 if (mediapackets.empty())
139 back = 0; front = bufferSize;
143 front = mediapackets.front().pos_buffer;
144 back = mediapackets.back().pos_buffer + mediapackets.back().length;
146 if (back == bufferSize) back = 0;
153 // The free space (if any) is in one continuous chunk.
154 if (len <= front - back) ret = len; // Is there enough of it?
156 else if (len <= bufferSize - back)
158 // There is enough space at the end of the buffer
161 else if (len <= front)
163 // There is enough space at the start of the buffer
168 if (ret) // Nonzero if we managed to find room for the packet
170 memcpy(outbuf + back, inbuf, len);
171 newPacket.pos_buffer = back;
173 mediapackets.push_back(newPacket);
178 // Log::getInstance()->log("Stream", Log::DEBUG, "We are full %d!",bufferSize);
184 bool Stream::drain(bool* dataavail)
188 if (dataavail) *dataavail = false;
190 if (draintarget->DrainTargetBufferFull()) return false; //We are full, no need to do something else
193 u4 listlength = mediapackets.size();
197 draintarget->PrepareMediaSample(mediapackets, cur_packet_pos);
200 if (dataavail && draintarget->DrainTargetReady()) *dataavail = true;
202 u4 consumed = draintarget->DeliverMediaSample(outbuf, &cur_packet_pos);
205 if (consumed != 0) ret = true;
207 if (consumed > listlength) consumed = listlength;
211 mediapackets.pop_front();