1 /*****************************************************************************
2 
3     MPEG Video Packetizer
4 
5     Copyright(C) 2004 John Cannon <spyder@matroska.org>
6 
7     This program 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.
11 
12     This program 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.
16 
17     You should have received a copy of the GNU General Public License
18     along with this program ; if not, write to the Free Software
19     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
20 
21  **/
22 
23 #include "common/common_pch.h"
24 #include "common/memory.h"
25 #include "common/output.h"
26 #include "M2VParser.h"
27 
28 constexpr auto BUFF_SIZE = 2 * 1024 * 1024;
29 
MPEGFrame(binary * n_data,uint32_t n_size,bool n_bCopy)30 MPEGFrame::MPEGFrame(binary *n_data, uint32_t n_size, bool n_bCopy):
31   size(n_size), bCopy(n_bCopy) {
32 
33   if(bCopy) {
34     data = (binary *)safemalloc(size);
35     memcpy(data, n_data, size);
36   } else {
37     data = n_data;
38   }
39   stamped        = false;
40   invisible      = false;
41   refs[0]        = -1;
42   refs[1]        = -1;
43   seqHdrData     = nullptr;
44   seqHdrDataSize = 0;
45 }
46 
~MPEGFrame()47 MPEGFrame::~MPEGFrame(){
48   safefree(data);
49   safefree(seqHdrData);
50 }
51 
SetEOS()52 void M2VParser::SetEOS(){
53   MPEGChunk * c;
54   while((c = mpgBuf->ReadChunk())){
55     chunks.push_back(c);
56   }
57   mpgBuf->ForceFinal();  //Force the last frame out.
58   c = mpgBuf->ReadChunk();
59   if(c) chunks.push_back(c);
60   FillQueues();
61   TimestampWaitingFrames();
62   m_eos = true;
63 }
64 
65 
WriteData(binary * data,uint32_t dataSize)66 int32_t M2VParser::WriteData(binary* data, uint32_t dataSize){
67   //If we are at EOS
68   if(m_eos)
69     return -1;
70 
71   if(mpgBuf->Feed(data, dataSize)){
72     return -1;
73   }
74 
75   //Fill the chunks buffer
76   while(mpgBuf->GetState() == MPEG2_BUFFER_STATE_CHUNK_READY){
77     MPEGChunk * c = mpgBuf->ReadChunk();
78     if(c) chunks.push_back(c);
79   }
80 
81   if(needInit){
82     if(InitParser() == 0)
83       needInit = false;
84   }
85 
86   FillQueues();
87   if(buffers.empty()){
88     parserState = MPV_PARSER_STATE_NEED_DATA;
89   }else{
90     parserState = MPV_PARSER_STATE_FRAME;
91   }
92 
93   return 0;
94 }
95 
DumpQueues()96 void M2VParser::DumpQueues(){
97   while(!chunks.empty()){
98     delete chunks.front();
99     chunks.erase(chunks.begin());
100   }
101   while(!buffers.empty()){
102     delete buffers.front();
103     buffers.pop();
104   }
105 }
106 
M2VParser()107 M2VParser::M2VParser()
108   : frameCounter{}
109   , throwOnError{}
110 {
111   mpgBuf = new MPEGVideoBuffer(BUFF_SIZE);
112 
113   notReachedFirstGOP = true;
114   previousTimestamp = 0;
115   previousDuration = 0;
116   waitExpectedTime = 0;
117   probing = false;
118   b_frame_warning_printed = false;
119   waitSecondField = false;
120   m_eos = false;
121   mpegVersion = 1;
122   needInit = true;
123   parserState = MPV_PARSER_STATE_NEED_DATA;
124   gopNum = -1;
125   frameNum = 0;
126   gopPts = 0;
127   highestPts = 0;
128   usePictureFrames = false;
129   seqHdrChunk = nullptr;
130   gopChunk = nullptr;
131   keepSeqHdrsInBitstream = true;
132 }
133 
InitParser()134 int32_t M2VParser::InitParser(){
135   //Gotta find a sequence header now
136   MPEGChunk* chunk;
137   //MPEGChunk* seqHdrChunk;
138   for (int i = 0, numChunks = chunks.size(); i < numChunks; i++){
139     chunk = chunks[i];
140     if(chunk->GetType() == MPEG_VIDEO_SEQUENCE_START_CODE){
141       //Copy the header for later, we must copy because the actual chunk will be deleted in a bit
142       binary * hdrData = new binary[chunk->GetSize()];
143       memcpy(hdrData, chunk->GetPointer(), chunk->GetSize());
144       seqHdrChunk = new MPEGChunk(hdrData, chunk->GetSize()); //Save this for adding as private data...
145       ParseSequenceHeader(chunk, m_seqHdr);
146 
147       //Look for sequence extension to identify mpeg2
148       binary* pData = chunk->GetPointer();
149       for (int j = 3, chunkSize = chunk->GetSize() - 4; j < chunkSize; j++){
150         if(pData[j] == 0x00 && pData[j+1] == 0x00 && pData[j+2] == 0x01 && pData[j+3] == 0xb5 && ((pData[j+4] & 0xF0) == 0x10)){
151           mpegVersion = 2;
152           break;
153         }
154       }
155       return 0;
156     }
157   }
158   return -1;
159 }
160 
~M2VParser()161 M2VParser::~M2VParser(){
162   DumpQueues();
163   FlushWaitQueue();
164   delete seqHdrChunk;
165   delete gopChunk;
166   delete mpgBuf;
167 }
168 
GetFrameDuration(MPEG2PictureHeader picHdr)169 MediaTime M2VParser::GetFrameDuration(MPEG2PictureHeader picHdr){
170   if (picHdr.repeatFirstField) {
171     // picHdr.progressive shall be 1 if picHdr.repeatFirstField is 1
172     if(m_seqHdr.progressiveSequence)
173       return picHdr.topFieldFirst ? 6 : 4;
174     else
175       return 3;
176   } else {
177     return picHdr.pictureStructure == MPEG2_PICTURE_TYPE_FRAME ? 2 : 1;
178   }
179 }
180 
GetState()181 MPEG2ParserState_e M2VParser::GetState(){
182   FillQueues();
183   if(!buffers.empty())
184     parserState = MPV_PARSER_STATE_FRAME;
185   else
186     parserState = MPV_PARSER_STATE_NEED_DATA;
187 
188   if(m_eos && parserState == MPV_PARSER_STATE_NEED_DATA)
189     parserState = MPV_PARSER_STATE_EOS;
190   return parserState;
191 }
192 
FlushWaitQueue()193 void M2VParser::FlushWaitQueue(){
194   waitSecondField = false;
195 
196   for (auto const &frame : waitQueue)
197     delete frame;
198   while (!buffers.empty()) {
199     delete buffers.front();
200     buffers.pop();
201   }
202 
203   waitQueue.clear();
204   m_timestamps.clear();
205 }
206 
StampFrame(MPEGFrame * frame)207 void M2VParser::StampFrame(MPEGFrame* frame){
208   if (m_timestamps.empty())
209     frame->timestamp = previousTimestamp + previousDuration;
210   else {
211     frame->timestamp = m_timestamps.front();
212     m_timestamps.pop_front();
213   }
214   previousTimestamp = frame->timestamp;
215   frame->duration = mtx::to_int(mtx::rational(frame->duration, 1) * 1'000'000'000 / (m_seqHdr.frameRate * 2));
216   previousDuration = frame->duration;
217 
218   frame->stamped = true;
219   frameTimestamps[frame->frameNumber] = frame->timestamp;
220 
221   // update affected ref timestamps
222   for (int i = 0; i < 2; i++)
223     if (refs[i].frameNumber == frame->frameNumber)
224       TryUpdate(refs[i]);
225 }
226 
UpdateFrame(MPEGFrame * frame)227 void M2VParser::UpdateFrame(MPEGFrame* frame){
228   // derive ref timestamps
229   for (int i = 0; i < 2; i++) {
230     if (!frame->tmpRefs[i].HasFrameNumber())
231       continue;
232     TryUpdate(frame->tmpRefs[i]);
233     assert(frame->tmpRefs[i].HasTimestamp()); // ensure the timestamp indeed has been set (sometime before)
234     frame->refs[i] = frame->tmpRefs[i].timestamp;
235   }
236 }
237 
OrderFrame(MPEGFrame * frame)238 int32_t M2VParser::OrderFrame(MPEGFrame* frame){
239   MPEGFrame *p = frame;
240 
241   // mxinfo(fmt::format("picStr {0} frame type {1} qt tc {2}\n", p->timestamp, static_cast<int>(p->pictureStructure), p->frameType));
242 
243   if (waitSecondField && (p->pictureStructure == MPEG2_PICTURE_TYPE_FRAME)){
244     auto error = Y("Unexpected picture frame after single field frame. Fix the MPEG2 video stream before attempting to multiplex it.\n");
245     if (throwOnError)
246       throw error;
247     mxerror(error);
248   }
249 
250   SetFrameRef(p);
251   ShoveRef(p);
252 
253   if (('I' == p->frameType) && !waitQueue.empty())
254     TimestampWaitingFrames();
255 
256   waitQueue.push_back(p);
257 
258   return 0;
259 }
260 
261 void
TimestampWaitingFrames()262 M2VParser::TimestampWaitingFrames() {
263   // mxinfo(fmt::format("  flushing {0}\n", waitQueue.size()));
264 
265   for (int idx = 0, numFrames = waitQueue.size(); idx < numFrames; ++idx)
266     waitQueue[idx]->decodingOrder = idx;
267 
268   std::sort(waitQueue.begin(), waitQueue.end(), [](MPEGFrame *a, MPEGFrame *b) { return a->timestamp < b->timestamp; });
269 
270   for (auto const &frame : waitQueue)
271     StampFrame(frame);
272   for (auto const &frame : waitQueue)
273     UpdateFrame(frame);
274 
275   std::sort(waitQueue.begin(), waitQueue.end(), [](MPEGFrame *a, MPEGFrame *b) { return a->decodingOrder < b->decodingOrder; });
276 
277   for (auto const &frame : waitQueue)
278     buffers.push(frame);
279   waitQueue.clear();
280 }
281 
PrepareFrame(MPEGChunk * chunk,MediaTime timestamp,MPEG2PictureHeader picHdr)282 int32_t M2VParser::PrepareFrame(MPEGChunk* chunk, MediaTime timestamp, MPEG2PictureHeader picHdr){
283   MPEGFrame* outBuf;
284   bool bCopy = true;
285   binary* pData = chunk->GetPointer();
286   uint32_t dataLen = chunk->GetSize();
287 
288   if ((seqHdrChunk && keepSeqHdrsInBitstream &&
289        (MPEG2_I_FRAME == picHdr.frameType)) || gopChunk) {
290     uint32_t pos = 0;
291     bCopy = false;
292     dataLen +=
293       (seqHdrChunk && keepSeqHdrsInBitstream && (MPEG2_I_FRAME == picHdr.frameType) ? seqHdrChunk->GetSize() : 0) +
294       (gopChunk ? gopChunk->GetSize() : 0);
295     pData = (binary *)safemalloc(dataLen);
296     if (seqHdrChunk && keepSeqHdrsInBitstream &&
297         (MPEG2_I_FRAME == picHdr.frameType)) {
298       memcpy(pData, seqHdrChunk->GetPointer(), seqHdrChunk->GetSize());
299       pos += seqHdrChunk->GetSize();
300       delete seqHdrChunk;
301       seqHdrChunk = nullptr;
302     }
303     if (gopChunk) {
304       memcpy(pData + pos, gopChunk->GetPointer(), gopChunk->GetSize());
305       pos += gopChunk->GetSize();
306       delete gopChunk;
307       gopChunk = nullptr;
308     }
309     memcpy(pData + pos, chunk->GetPointer(), chunk->GetSize());
310   }
311 
312   outBuf = new MPEGFrame(pData, dataLen, bCopy);
313   outBuf->frameNumber = frameCounter++;
314 
315   if (seqHdrChunk && !keepSeqHdrsInBitstream &&
316       (MPEG2_I_FRAME == picHdr.frameType)) {
317     outBuf->seqHdrData = (binary *)safemalloc(seqHdrChunk->GetSize());
318     outBuf->seqHdrDataSize = seqHdrChunk->GetSize();
319     memcpy(outBuf->seqHdrData, seqHdrChunk->GetPointer(),
320            outBuf->seqHdrDataSize);
321     delete seqHdrChunk;
322     seqHdrChunk = nullptr;
323   }
324 
325   if(picHdr.frameType == MPEG2_I_FRAME){
326     outBuf->frameType = 'I';
327   }else if(picHdr.frameType == MPEG2_P_FRAME){
328     outBuf->frameType = 'P';
329   }else{
330     outBuf->frameType = 'B';
331   }
332 
333   outBuf->timestamp = timestamp; // Still the sequence number
334 
335   outBuf->invisible = invisible;
336   outBuf->duration = GetFrameDuration(picHdr);
337   outBuf->rff = (picHdr.repeatFirstField != 0);
338   outBuf->tff = (picHdr.topFieldFirst != 0);
339   outBuf->progressive = (picHdr.progressive != 0);
340   outBuf->pictureStructure = (uint8_t) picHdr.pictureStructure;
341 
342   OrderFrame(outBuf);
343   return 0;
344 }
345 
SetFrameRef(MPEGFrame * ref)346 void M2VParser::SetFrameRef(MPEGFrame *ref){
347   if (ref->frameType == 'B') {
348     ref->tmpRefs[0] = refs[0];
349     ref->tmpRefs[1] = refs[1];
350   } else if(ref->frameType == 'P')
351     ref->tmpRefs[0] = refs[1];
352 }
353 
ShoveRef(MPEGFrame * ref)354 void M2VParser::ShoveRef(MPEGFrame *ref){
355   if(ref->frameType == 'I' || ref->frameType == 'P'){
356     refs[0] = refs[1];
357     refs[1].Clear();
358     refs[1].frameNumber = ref->frameNumber;
359   }
360 }
361 
ClearRef()362 void M2VParser::ClearRef(){
363   for (int i = 0; i < 2; i++)
364     refs[i].Clear();
365 }
366 
367 //Maintains the time of the last start of GOP and uses the temporal_reference
368 //field as an offset.
FillQueues()369 int32_t M2VParser::FillQueues(){
370   if(chunks.empty()){
371     return -1;
372   }
373   bool done = false;
374   while(!done){
375     MediaTime myTime;
376     MPEGChunk* chunk = chunks.front();
377     while (chunk->GetType() != MPEG_VIDEO_PICTURE_START_CODE) {
378       if (chunk->GetType() == MPEG_VIDEO_GOP_START_CODE) {
379         ParseGOPHeader(chunk, m_gopHdr);
380         if (frameNum != 0) {
381           gopPts = highestPts + 1;
382         }
383         if (gopChunk)
384           delete gopChunk;
385         gopChunk = chunk;
386         gopNum++;
387         /* Perform some sanity checks */
388         if(waitSecondField){
389           auto error = Y("Single field frame before GOP header detected. Fix the MPEG2 video stream before attempting to multiplex it.\n");
390           if (throwOnError)
391             throw error;
392           mxerror(error);
393         }
394         // There are too many broken videos to do the following so ReferenceBlock will be wrong for broken videos.
395         /*
396         if(m_gopHdr.closedGOP){
397           ClearRef();
398         }
399         */
400       } else if (chunk->GetType() == MPEG_VIDEO_SEQUENCE_START_CODE) {
401         if (seqHdrChunk)
402           delete seqHdrChunk;
403         ParseSequenceHeader(chunk, m_seqHdr);
404         seqHdrChunk = chunk;
405 
406       }
407 
408       chunks.erase(chunks.begin());
409       if (chunks.empty())
410         return -1;
411       chunk = chunks.front();
412     }
413     MPEG2PictureHeader picHdr;
414     ParsePictureHeader(chunk, picHdr);
415 
416     if (picHdr.pictureStructure == MPEG2_PICTURE_TYPE_FRAME) {
417       usePictureFrames = true;
418     }
419     myTime = gopPts + picHdr.temporalReference;
420     invisible = false;
421 
422     if (myTime > highestPts)
423       highestPts = myTime;
424 
425     switch(picHdr.frameType){
426       case MPEG2_I_FRAME:
427         PrepareFrame(chunk, myTime, picHdr);
428         notReachedFirstGOP = false;
429         break;
430       case MPEG2_P_FRAME:
431         if (!refs[1].HasFrameNumber())
432           break;
433         PrepareFrame(chunk, myTime, picHdr);
434         break;
435       default: //B-frames
436         if (!refs[0].HasFrameNumber() || !refs[1].HasFrameNumber()) {
437           if (!m_gopHdr.closedGOP && !m_gopHdr.brokenLink && !probing && !b_frame_warning_printed) {
438             mxwarn(Y("Found at least one B frame without second reference in a non closed GOP.\n"));
439             b_frame_warning_printed = true;
440           }
441           invisible = true;
442         }
443         PrepareFrame(chunk, myTime, picHdr);
444     }
445     frameNum++;
446     chunks.erase(chunks.begin());
447     delete chunk;
448     if (chunks.empty())
449       return -1;
450   }
451   return 0;
452 }
453 
ReadFrame()454 MPEGFrame* M2VParser::ReadFrame(){
455   //if(m_eos) return nullptr;
456   if(GetState() != MPV_PARSER_STATE_FRAME){
457     return nullptr;
458   }
459   if(buffers.empty()){
460     return nullptr; // OOPS!
461   }
462   MPEGFrame* frame = buffers.front();
463   buffers.pop();
464   return frame;
465 }
466 
467 void
AddTimestamp(int64_t timestamp)468 M2VParser::AddTimestamp(int64_t timestamp) {
469   std::list<int64_t>::iterator idx = m_timestamps.begin();
470   while ((idx != m_timestamps.end()) && (timestamp > *idx))
471     idx++;
472   m_timestamps.insert(idx, timestamp);
473 }
474 
475 void
SetThrowOnError(bool doThrow)476 M2VParser::SetThrowOnError(bool doThrow) {
477   throwOnError = doThrow;
478 }
479 
480 void
TryUpdate(MPEGFrameRef & frame)481 M2VParser::TryUpdate(MPEGFrameRef &frame){
482   // if frame set, stamped and no timestamp yet, derive it
483   if (frame.HasTimestamp() || !frame.HasFrameNumber())
484     return;
485 
486   auto itr = frameTimestamps.find(frame.frameNumber);
487   if (itr != frameTimestamps.end())
488     frame.timestamp = itr->second;
489 }
490