~ubuntu-branches/ubuntu/hoary/kdemultimedia/hoary

« back to all changes in this revision

Viewing changes to mpeglib/lib/mpegplay/videoDecoder.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Martin Schulze
  • Date: 2003-01-22 15:00:51 UTC
  • Revision ID: james.westby@ubuntu.com-20030122150051-uihwkdoxf15mi1tn
Tags: upstream-2.2.2
ImportĀ upstreamĀ versionĀ 2.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  mpeg I video decoder (derived from mpeg_play)
 
3
  Copyright (C) 2000  Martin Vogt
 
4
 
 
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.
 
8
 
 
9
  For more information look at the file COPYRIGHT in this package
 
10
 
 
11
 */
 
12
 
 
13
 
 
14
 
 
15
#include "videoDecoder.h"
 
16
 
 
17
 
 
18
 
 
19
 
 
20
 
 
21
VideoDecoder::VideoDecoder(MpegVideoStream* inputStream,
 
22
                           MpegVideoHeader* initSequence) {
 
23
 
 
24
  /* Check for legal buffer length. */
 
25
 
 
26
  init_tables();
 
27
 
 
28
 
 
29
  /* Initialize fields that used to be global */
 
30
 
 
31
  mpegVideoStream=inputStream;
 
32
  decoderClass=new DecoderClass(this,mpegVideoStream);
 
33
  recon=new Recon();
 
34
  motionVector=new MotionVector();
 
35
  slice=new Slice();
 
36
  group=new GOP();
 
37
  mpegVideoHeader=new MpegVideoHeader();
 
38
  picture=new Picture();
 
39
  macroBlock=new MacroBlock(this);
 
40
 
 
41
  // init this stream with the init sequence
 
42
  initSequence->copyTo(mpegVideoHeader);
 
43
 
 
44
  syncState=SYNC_TO_CLOSED_GOP;
 
45
  extension=new MpegExtension();
 
46
  frameCounter=0;
 
47
}
 
48
 
 
49
 
 
50
VideoDecoder::~VideoDecoder() {
 
51
 
 
52
  delete mpegVideoHeader;
 
53
  delete picture;
 
54
  delete decoderClass;
 
55
  delete recon;
 
56
  delete motionVector;
 
57
  delete slice;
 
58
  delete group;
 
59
  delete extension;
 
60
  delete macroBlock;
 
61
}
 
62
 
 
63
 
 
64
 
 
65
 
 
66
 
 
67
/*
 
68
 *--------------------------------------------------------------
 
69
 *
 
70
 * mpegVidRsrc --
 
71
 *
 
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.
 
83
 *
 
84
 * Results:
 
85
 *      A pointer to the video stream structure used.
 
86
 *
 
87
 * Side effects:
 
88
 *      Bit stream is irreversibly parsed. If a picture is completed,
 
89
 *      a function is called to display the frame at the correct time.
 
90
 *
 
91
 *--------------------------------------------------------------
 
92
 */
 
93
 
 
94
int VideoDecoder::mpegVidRsrc(PictureArray* pictureArray) {
 
95
  int back=_SYNC_TO_NONE;
 
96
 
 
97
  unsigned int data;
 
98
  int i;
 
99
 
 
100
 
 
101
  /*
 
102
   * If called for the first time, find start code, make sure it is a
 
103
   * sequence start code.
 
104
   */
 
105
 
 
106
 
 
107
  /* Get next 32 bits (size of start codes). */
 
108
 
 
109
  data=mpegVideoStream->showBits(32);
 
110
 
 
111
 
 
112
  /*
 
113
   * Process according to start code (or parse macroblock if not a start code
 
114
   * at all).
 
115
   */
 
116
  switch (data) {
 
117
    /*
 
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);
 
123
    */
 
124
  case SEQ_END_CODE:
 
125
  case ISO_11172_END_CODE:   /*  handle ISO_11172_END_CODE too */
 
126
 
 
127
    /* Display last frame. */
 
128
 
 
129
    // removed!
 
130
 
 
131
    /* Sequence done. Do the right thing. For right now, exit. */
 
132
 
 
133
 
 
134
    cout << "******** flushin end code"<<endl;
 
135
    mpegVideoStream->flushBits(32);
 
136
    goto done;
 
137
    break;
 
138
  case EXT_START_CODE:
 
139
    cout << "found EXT_START_CODE skipping"<<endl;
 
140
    mpegVideoStream->flushBits(32);
 
141
    /* Goto next start code. */
 
142
    mpegVideoStream->next_start_code();
 
143
 
 
144
    break;
 
145
  case USER_START_CODE:
 
146
    mpegVideoStream->flushBits(32);
 
147
    /* Goto next start code. */
 
148
    mpegVideoStream->next_start_code();
 
149
 
 
150
    break;
 
151
  case SEQ_START_CODE:
 
152
    
 
153
    /* Sequence start code. Parse sequence header. */
 
154
    if (ParseSeqHead() == false) {
 
155
      printf("SEQ_START_CODE 1-error\n");
 
156
      goto error;
 
157
    }
 
158
    goto done;
 
159
 
 
160
  case GOP_START_CODE:
 
161
    /* Group of Pictures start code. Parse gop header. */
 
162
    if (ParseGOP() == false) {
 
163
      printf("GOP_START_CODE 1-error\n");
 
164
      goto error;
 
165
    }
 
166
    goto done;
 
167
 
 
168
  case PICTURE_START_CODE:
 
169
 
 
170
    /* Picture start code. Parse picture header and first slice header. */
 
171
 
 
172
    
 
173
    back=ParsePicture();
 
174
    if (back != _SYNC_TO_NONE) {
 
175
      //cout << "skip B Frame we are late"<<endl;
 
176
      return back;
 
177
    }
 
178
 
 
179
    // parse ok
 
180
    if (ParseSlice() == false) {
 
181
      printf("PICTURE_START_CODE 2-error\n");
 
182
      goto error;
 
183
    }
 
184
    break;
 
185
 
 
186
  case SEQUENCE_ERROR_CODE:
 
187
    mpegVideoStream->flushBits(32);
 
188
    mpegVideoStream->next_start_code();
 
189
 
 
190
    goto done;
 
191
 
 
192
    
 
193
  default:
 
194
 
 
195
    /* Check for slice start code. */
 
196
    if ((data >= SLICE_MIN_START_CODE) && (data <= SLICE_MAX_START_CODE)) {
 
197
 
 
198
      /* Slice start code. Parse slice header. */
 
199
      if (ParseSlice() == false) {
 
200
        printf("default 1-error\n");
 
201
        goto error;
 
202
      }
 
203
    }
 
204
    break;
 
205
  }
 
206
 
 
207
  /* Parse next MB_QUANTUM macroblocks. */
 
208
  for (i = 0; i < MB_QUANTUM; i++) {
 
209
 
 
210
    /* Check to see if actually a startcode and not a macroblock. */
 
211
    data=mpegVideoStream->showBits(23);
 
212
    if (data != 0x0) {
 
213
      /* Not start code. Parse Macroblock. fill yuv pictures*/
 
214
      if (macroBlock->processMacroBlock(pictureArray) == false) {
 
215
        goto error;
 
216
      }
 
217
    } else {
 
218
      /* Not macroblock, actually start code. Get start code. */
 
219
      mpegVideoStream->next_start_code();
 
220
 
 
221
      /*
 
222
       * If start code is outside range of slice start codes, frame is
 
223
       * complete, display frame.
 
224
       */
 
225
      data=mpegVideoStream->showBits(32);
 
226
 
 
227
      if (((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) &&
 
228
          (data != SEQUENCE_ERROR_CODE)) {
 
229
        doPictureDisplay(pictureArray);
 
230
      }
 
231
      goto done;
 
232
    }
 
233
  }
 
234
  data=mpegVideoStream->showBits(23);
 
235
  /* Check if we just finished a picture on the MB_QUANTUM macroblock */
 
236
  if (data == 0x0) {
 
237
    mpegVideoStream->next_start_code();
 
238
 
 
239
    data=mpegVideoStream->showBits(32);
 
240
    if ((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) {
 
241
      doPictureDisplay(pictureArray);
 
242
    }
 
243
  }
 
244
 
 
245
  /* Return pointer to video stream structure. */
 
246
 
 
247
  goto done;
 
248
 
 
249
error:
 
250
  init_tables();
 
251
  back=_SYNC_TO_GOP;
 
252
  mpegVideoHeader->init_quanttables();
 
253
 
 
254
  goto done;
 
255
 
 
256
done:
 
257
  return back;
 
258
 
 
259
}
 
260
 
 
261
 
 
262
 
 
263
 
 
264
 
 
265
 
 
266
int VideoDecoder::ParseSeqHead() {
 
267
  int back;
 
268
 
 
269
  /* Flush off sequence start code. */
 
270
 
 
271
  mpegVideoStream->flushBits(32);
 
272
 
 
273
  back=mpegVideoHeader->parseSeq(mpegVideoStream);
 
274
 
 
275
  return back;
 
276
 
 
277
}
 
278
 
 
279
 
 
280
 
 
281
 
 
282
int VideoDecoder::ParseGOP() {
 
283
  if (syncState==SYNC_TO_CLOSED_GOP) {
 
284
    syncState=SYNC_HAS_CLOSED_GOP;
 
285
  }
 
286
 
 
287
  return group->processGOP(mpegVideoStream);
 
288
}
 
289
 
 
290
 
 
291
 
 
292
 
 
293
int VideoDecoder::ParsePicture() {
 
294
  int back;
 
295
  back=picture->processPicture(mpegVideoStream);
 
296
 
 
297
  macroBlock->resetPastMacroBlock();
 
298
  if (back == false) {
 
299
    return _SYNC_TO_GOP;
 
300
  }
 
301
 
 
302
 
 
303
  return _SYNC_TO_NONE;
 
304
}
 
305
 
 
306
 
 
307
 
 
308
int VideoDecoder::ParseSlice() {
 
309
 
 
310
  
 
311
  slice->parseSlice(mpegVideoStream);
 
312
  macroBlock->resetMacroBlock();
 
313
  decoderClass->resetDCT();
 
314
  return true;
 
315
}
 
316
 
 
317
 
 
318
 
 
319
 
 
320
/**
 
321
   After a seek we can only start with an I frame
 
322
*/
 
323
 
 
324
void VideoDecoder::resyncToI_Frame() {
 
325
 
 
326
  syncState=SYNC_TO_CLOSED_GOP;
 
327
}
 
328
 
 
329
 
 
330
void VideoDecoder::doPictureDisplay(PictureArray* pictureArray) {
 
331
 
 
332
 
 
333
  // insert end timestamp to current picture
 
334
  YUVPicture* pic=pictureArray->getCurrent();
 
335
  unsigned int code_type=picture->getCodeType();
 
336
 
 
337
  TimeStamp* startTimeStamp=picture->getStartOfPicStamp();
 
338
 
 
339
  pic->setStartTimeStamp(startTimeStamp);
 
340
  float rate=mpegVideoHeader->getPictureRate();
 
341
 
 
342
  pictureArray->setPicturePerSecond(rate);
 
343
 
 
344
 
 
345
 
 
346
  pic->setMpegPictureType(code_type);
 
347
 
 
348
  if (syncState < SYNC_HAS_CLOSED_GOP) {
 
349
    return;
 
350
  }
 
351
  if (syncState < SYNC_HAS_I_FRAME_SYNC) {
 
352
    if (code_type != I_TYPE) {
 
353
      return;
 
354
    }
 
355
  }
 
356
  if (code_type == I_TYPE) {
 
357
    YUVPicture* past=pictureArray->getPast();
 
358
    YUVPicture* future=pictureArray->getFuture();
 
359
    YUVPicture* current=pictureArray->getCurrent();
 
360
 
 
361
    YUVPicture* tmp=past;
 
362
    past = future;
 
363
    future = current;
 
364
    current = tmp;
 
365
    
 
366
    pic=past;
 
367
 
 
368
  
 
369
    pictureArray->setPast(past);
 
370
    pictureArray->setCurrent(current);
 
371
    pictureArray->setFuture(future);
 
372
 
 
373
    if (syncState < SYNC_HAS_I_FRAME_SYNC) {
 
374
      syncState=SYNC_HAS_I_FRAME_SYNC;
 
375
      return;
 
376
    }
 
377
    if (syncState == SYNC_HAS_P_FRAME_SYNC) {
 
378
      syncState=SYNC_HAS_FRAME_SYNC;
 
379
      return;
 
380
    }     
 
381
    if (syncState == SYNC_HAS_I_FRAME_SYNC) {
 
382
      syncState=SYNC_HAS_P_FRAME_SYNC;
 
383
      return;
 
384
    }    
 
385
 
 
386
 
 
387
  
 
388
  }
 
389
  
 
390
  if (code_type == P_TYPE) {
 
391
    YUVPicture* past=pictureArray->getPast();
 
392
    YUVPicture* future=pictureArray->getFuture();
 
393
    YUVPicture* current=pictureArray->getCurrent();
 
394
 
 
395
    YUVPicture* tmp=past;
 
396
    past = future;
 
397
    future = current;
 
398
    current = tmp;
 
399
       
 
400
    pic = past;
 
401
 
 
402
 
 
403
   
 
404
    pictureArray->setPast(past);
 
405
    pictureArray->setCurrent(current);
 
406
    pictureArray->setFuture(future);
 
407
 
 
408
    if (syncState < SYNC_HAS_P_FRAME_SYNC) {
 
409
      syncState=SYNC_HAS_P_FRAME_SYNC;
 
410
      return;
 
411
    }
 
412
 
 
413
  }  
 
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();
 
418
      pic=past;
 
419
    }   
 
420
    /**
 
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
 
424
       we swap them.
 
425
    */
 
426
    YUVPicture* pframe=pictureArray->getFuture();
 
427
    YUVPicture* bframe=pictureArray->getCurrent();
 
428
 
 
429
    TimeStamp* pTime=pframe->getStartTimeStamp();
 
430
    TimeStamp* bTime=bframe->getStartTimeStamp();
 
431
 
 
432
    double pPTS=pTime->getPTSTimeStamp();
 
433
    double bPTS=bTime->getPTSTimeStamp();
 
434
    if (pPTS < bPTS) {
 
435
      //cout << "********P/B Frame PTS error -> enable swap and pray"<<endl;
 
436
      bTime->copyTo(pTime);
 
437
    }
 
438
   
 
439
 
 
440
 
 
441
    // we display the current picture
 
442
    // (already set)
 
443
  }
 
444
 
 
445
  
 
446
  if (pic == NULL) {
 
447
    cout << "pic NULL"<<endl;
 
448
    exit(0);
 
449
    return;
 
450
  }
 
451
  if (syncState < SYNC_HAS_FRAME_SYNC) {
 
452
    return;
 
453
  }
 
454
 
 
455
  double val=pictureArray->getPicturePerSecond();
 
456
  pic->setPicturePerSecond(val);
 
457
 
 
458
  TimeStamp* currentStamp=pic->getStartTimeStamp();
 
459
 
 
460
 
 
461
  frameCounter++;
 
462
 
 
463
  if (currentStamp->getPTSFlag()==true) {
 
464
    frameCounter=0;
 
465
  }
 
466
  currentStamp->setVideoFrameCounter(frameCounter);
 
467
 
 
468
 
 
469
  // let plugin "rip" the picture
 
470
  pictureArray->setYUVPictureCallback(pic);
 
471
}
 
472
 
 
473
 
 
474
 
 
475
 
 
476