2
mpeg I video decoder (derived from mpeg_play)
3
Copyright (C) 2000 Martin Vogt
5
This program is free software; you can redistribute it and/or modify
6
it under the terms of the GNU Library General Public License as published by
7
the Free Software Foundation.
9
For more information look at the file COPYRIGHT in this package
15
#include "videoDecoder.h"
21
VideoDecoder::VideoDecoder(MpegVideoStream* inputStream,
22
MpegVideoHeader* initSequence) {
24
/* Check for legal buffer length. */
29
/* Initialize fields that used to be global */
31
mpegVideoStream=inputStream;
32
decoderClass=new DecoderClass(this,mpegVideoStream);
34
motionVector=new MotionVector();
37
mpegVideoHeader=new MpegVideoHeader();
38
picture=new Picture();
39
macroBlock=new MacroBlock(this);
41
// init this stream with the init sequence
42
initSequence->copyTo(mpegVideoHeader);
44
syncState=SYNC_TO_CLOSED_GOP;
45
extension=new MpegExtension();
50
VideoDecoder::~VideoDecoder() {
52
delete mpegVideoHeader;
68
*--------------------------------------------------------------
72
* Parses bit stream until MB_QUANTUM number of
73
* macroblocks have been decoded or current slice or
74
* picture ends, whichever comes first. If the start
75
* of a frame is encountered, the frame is time stamped
76
* with the value passed in time_stamp. If the value
77
* passed in buffer is not null, the video stream buffer
78
* is set to buffer and the length of the buffer is
79
* expected in value passed in through length. The current
80
* video stream is set to vid_stream. If vid_stream
81
* is passed as NULL, a new VideoDecoder structure is created
82
* and initialized and used as the current video stream.
85
* A pointer to the video stream structure used.
88
* Bit stream is irreversibly parsed. If a picture is completed,
89
* a function is called to display the frame at the correct time.
91
*--------------------------------------------------------------
94
int VideoDecoder::mpegVidRsrc(PictureArray* pictureArray) {
95
int back=_SYNC_TO_NONE;
102
* If called for the first time, find start code, make sure it is a
103
* sequence start code.
107
/* Get next 32 bits (size of start codes). */
109
data=mpegVideoStream->showBits(32);
113
* Process according to start code (or parse macroblock if not a start code
118
case PACK_START_CODE:
119
case SYSTEM_HEADER_START_CODE:
120
cout << "Packet in Loop **************"<<endl;
121
mpegVideoStream->flushBits(32);
122
packet->read_sys(data,vid_stream->bufferReader);
125
case ISO_11172_END_CODE: /* handle ISO_11172_END_CODE too */
127
/* Display last frame. */
131
/* Sequence done. Do the right thing. For right now, exit. */
134
cout << "******** flushin end code"<<endl;
135
mpegVideoStream->flushBits(32);
139
cout << "found EXT_START_CODE skipping"<<endl;
140
mpegVideoStream->flushBits(32);
141
/* Goto next start code. */
142
mpegVideoStream->next_start_code();
145
case USER_START_CODE:
146
mpegVideoStream->flushBits(32);
147
/* Goto next start code. */
148
mpegVideoStream->next_start_code();
153
/* Sequence start code. Parse sequence header. */
154
if (ParseSeqHead() == false) {
155
printf("SEQ_START_CODE 1-error\n");
161
/* Group of Pictures start code. Parse gop header. */
162
if (ParseGOP() == false) {
163
printf("GOP_START_CODE 1-error\n");
168
case PICTURE_START_CODE:
170
/* Picture start code. Parse picture header and first slice header. */
174
if (back != _SYNC_TO_NONE) {
175
//cout << "skip B Frame we are late"<<endl;
180
if (ParseSlice() == false) {
181
printf("PICTURE_START_CODE 2-error\n");
186
case SEQUENCE_ERROR_CODE:
187
mpegVideoStream->flushBits(32);
188
mpegVideoStream->next_start_code();
195
/* Check for slice start code. */
196
if ((data >= SLICE_MIN_START_CODE) && (data <= SLICE_MAX_START_CODE)) {
198
/* Slice start code. Parse slice header. */
199
if (ParseSlice() == false) {
200
printf("default 1-error\n");
207
/* Parse next MB_QUANTUM macroblocks. */
208
for (i = 0; i < MB_QUANTUM; i++) {
210
/* Check to see if actually a startcode and not a macroblock. */
211
data=mpegVideoStream->showBits(23);
213
/* Not start code. Parse Macroblock. fill yuv pictures*/
214
if (macroBlock->processMacroBlock(pictureArray) == false) {
218
/* Not macroblock, actually start code. Get start code. */
219
mpegVideoStream->next_start_code();
222
* If start code is outside range of slice start codes, frame is
223
* complete, display frame.
225
data=mpegVideoStream->showBits(32);
227
if (((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) &&
228
(data != SEQUENCE_ERROR_CODE)) {
229
doPictureDisplay(pictureArray);
234
data=mpegVideoStream->showBits(23);
235
/* Check if we just finished a picture on the MB_QUANTUM macroblock */
237
mpegVideoStream->next_start_code();
239
data=mpegVideoStream->showBits(32);
240
if ((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) {
241
doPictureDisplay(pictureArray);
245
/* Return pointer to video stream structure. */
252
mpegVideoHeader->init_quanttables();
266
int VideoDecoder::ParseSeqHead() {
269
/* Flush off sequence start code. */
271
mpegVideoStream->flushBits(32);
273
back=mpegVideoHeader->parseSeq(mpegVideoStream);
282
int VideoDecoder::ParseGOP() {
283
if (syncState==SYNC_TO_CLOSED_GOP) {
284
syncState=SYNC_HAS_CLOSED_GOP;
287
return group->processGOP(mpegVideoStream);
293
int VideoDecoder::ParsePicture() {
295
back=picture->processPicture(mpegVideoStream);
297
macroBlock->resetPastMacroBlock();
303
return _SYNC_TO_NONE;
308
int VideoDecoder::ParseSlice() {
311
slice->parseSlice(mpegVideoStream);
312
macroBlock->resetMacroBlock();
313
decoderClass->resetDCT();
321
After a seek we can only start with an I frame
324
void VideoDecoder::resyncToI_Frame() {
326
syncState=SYNC_TO_CLOSED_GOP;
330
void VideoDecoder::doPictureDisplay(PictureArray* pictureArray) {
333
// insert end timestamp to current picture
334
YUVPicture* pic=pictureArray->getCurrent();
335
unsigned int code_type=picture->getCodeType();
337
TimeStamp* startTimeStamp=picture->getStartOfPicStamp();
339
pic->setStartTimeStamp(startTimeStamp);
340
float rate=mpegVideoHeader->getPictureRate();
342
pictureArray->setPicturePerSecond(rate);
346
pic->setMpegPictureType(code_type);
348
if (syncState < SYNC_HAS_CLOSED_GOP) {
351
if (syncState < SYNC_HAS_I_FRAME_SYNC) {
352
if (code_type != I_TYPE) {
356
if (code_type == I_TYPE) {
357
YUVPicture* past=pictureArray->getPast();
358
YUVPicture* future=pictureArray->getFuture();
359
YUVPicture* current=pictureArray->getCurrent();
361
YUVPicture* tmp=past;
369
pictureArray->setPast(past);
370
pictureArray->setCurrent(current);
371
pictureArray->setFuture(future);
373
if (syncState < SYNC_HAS_I_FRAME_SYNC) {
374
syncState=SYNC_HAS_I_FRAME_SYNC;
377
if (syncState == SYNC_HAS_P_FRAME_SYNC) {
378
syncState=SYNC_HAS_FRAME_SYNC;
381
if (syncState == SYNC_HAS_I_FRAME_SYNC) {
382
syncState=SYNC_HAS_P_FRAME_SYNC;
390
if (code_type == P_TYPE) {
391
YUVPicture* past=pictureArray->getPast();
392
YUVPicture* future=pictureArray->getFuture();
393
YUVPicture* current=pictureArray->getCurrent();
395
YUVPicture* tmp=past;
404
pictureArray->setPast(past);
405
pictureArray->setCurrent(current);
406
pictureArray->setFuture(future);
408
if (syncState < SYNC_HAS_P_FRAME_SYNC) {
409
syncState=SYNC_HAS_P_FRAME_SYNC;
414
if (code_type == B_TYPE) {
415
if (syncState == SYNC_HAS_P_FRAME_SYNC) {
416
syncState=SYNC_HAS_FRAME_SYNC;
417
YUVPicture* past=pictureArray->getPast();
421
Now check for PTS timeStamp error. It seems some encoders
422
handles this different.
423
If the P frame has a timeStamp earlier than our B stamp
426
YUVPicture* pframe=pictureArray->getFuture();
427
YUVPicture* bframe=pictureArray->getCurrent();
429
TimeStamp* pTime=pframe->getStartTimeStamp();
430
TimeStamp* bTime=bframe->getStartTimeStamp();
432
double pPTS=pTime->getPTSTimeStamp();
433
double bPTS=bTime->getPTSTimeStamp();
435
//cout << "********P/B Frame PTS error -> enable swap and pray"<<endl;
436
bTime->copyTo(pTime);
441
// we display the current picture
447
cout << "pic NULL"<<endl;
451
if (syncState < SYNC_HAS_FRAME_SYNC) {
455
double val=pictureArray->getPicturePerSecond();
456
pic->setPicturePerSecond(val);
458
TimeStamp* currentStamp=pic->getStartTimeStamp();
463
if (currentStamp->getPTSFlag()==true) {
466
currentStamp->setVideoFrameCounter(frameCounter);
469
// let plugin "rip" the picture
470
pictureArray->setYUVPictureCallback(pic);