[Libav-user] mpeg4 decoding only decodes 36395 out of 154959 frames

Bob Self bobslf at gmail.com
Fri May 11 11:12:39 CEST 2012


I finally found an incomplete example that I was able to get sort-of working
with non-deprecated functions. The only error (or warning?) that I get is
"[mpeg4 @ 0x1367c80] Invalid and inefficient vfw-avi packed B frames detected"
once. Other than that the program runs without errors, but there is still
something that I don't understand.

pFormatCtx->streams[videoStream]->nb_frames says that there are 154,959 frames
But if I count the decoded frames (frame++), I only get 36,395 frames
before the loop quits. Why does this happen?



the program output:
-------------------------------

[avi @ 0x1361920] Format avi probed with size=2048 and score=100
[AVI demuxer @ 0x1361e60] use odml:1
st:1 removing common factor 128 from timebase
[mpeg4 @ 0x1367c80] Invalid and inefficient vfw-avi packed B frames detected
[avi @ 0x1361920] All info found
Input #0, avi, from 'test.avi':
  Metadata:
    encoder         : FairUse Wizard - http://fairusewizard.com
  Duration: 01:47:43.08, start: 0.000000, bitrate: 1815 kb/s
    Stream #0:0, 1, 1001/24000: Video: mpeg4 (Advanced Simple Profile)
(XVID / 0x44495658), yuv420p, 688x368 [SAR 1:1 DAR 43:23], 1001/24000,
23.98 tbr, 23.98 tbn, 23.98 tbc
    Stream #0:1, 21, 3/125: Audio: mp3 (U[0][0][0] / 0x0055), 48000
Hz, stereo, s16, 128 kb/s


the test function:
----------------------------

int test(void)  {
   const char *inputfile = "test.avi";
   int totalFrames = 0;
   int frameLocation = 0;
   AVFormatContext *pFormatCtx;
   unsigned int    i, videoStream;
   AVCodecContext  *pCodecCtx;
   AVCodec         *pCodec;
   AVFrame         *pFrame;
   AVFrame         *pFrameYUV;
   int             numBytes;
   uint8_t         *buffer;
   int status;
   unsigned int codec_version;

   av_register_all();

   codec_version = avcodec_version();
   // avcodec version: 54.10.100
   printf("avcodec version = %d.%d.%d\n",
(codec_version&0x00ff0000)>>16, (codec_version&0x0000ff00)>>8,
codec_version&0x000000ff);      // version 52.72.2

   av_log_set_level(AV_LOG_DEBUG);

   pFormatCtx = avformat_alloc_context();

   status = avformat_open_input(&pFormatCtx, inputfile, NULL, NULL);
   if (status != 0)  {
      return -1;
   }

   status = avformat_find_stream_info(pFormatCtx, NULL);
   if (status<0)  {
      return -2;
   }

   av_dump_format(pFormatCtx, 0, inputfile, false);

   videoStream=-1;

   for(i=0; i<pFormatCtx->nb_streams; i++) {
      if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
         videoStream=i;
         break;
      }
   }
   if(videoStream==-1) {
      return -3;
   }

   pCodecCtx = pFormatCtx->streams[videoStream]->codec;

   double duration = double(pFormatCtx->duration) / AV_TIME_BASE;

   pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
   if(pCodec==NULL) {
      return -4;
   }

   if(pCodec->capabilities & CODEC_CAP_TRUNCATED)  {
      pCodecCtx->flags|=CODEC_FLAG_TRUNCATED;
   }

   if(avcodec_open2(pCodecCtx, pCodec, NULL)<0)  {
      return -5;
   }

   printf("Using codec: %s\n", pCodec->name);

   pFrame = avcodec_alloc_frame();

   pFrameYUV=avcodec_alloc_frame();
   if(pFrameYUV==NULL)  {
      return -6;
   }

   numBytes = avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width,
pCodecCtx->height);       // 379776
   buffer = (uint8_t *)av_malloc(numBytes*sizeof(uint8_t));

   avpicture_fill((AVPicture *)pFrameYUV, buffer, PIX_FMT_YUV420P,
pCodecCtx->width, pCodecCtx->height);

   totalFrames = pFormatCtx->streams[videoStream]->nb_frames;
   // 154959
   printf("Frames: %d\n", totalFrames);

   AVPacket packet;
   int isFrameFinished = 0;
   int pixelScanCount = 0;

   printf("video width = %d\n", pCodecCtx->width);
   printf("video height = %d\n", pCodecCtx->height);

   int frame = 0;
   int loops = 0;

   while (av_read_frame(pFormatCtx, &packet) >= 0)  {
      status = av_read_frame(pFormatCtx, &packet);
      if (status<0)  {
         break;
      }

      loops++;

      if (packet.stream_index == videoStream)  {
         status = avcodec_decode_video2(pCodecCtx, pFrame,
&isFrameFinished, &packet);
         if (isFrameFinished) {
            frame++;

            if ( (frame%1000) == 0)  {
               printf("%d\n", frame);
            }

            pixelScanCount = 0;

            for (int y = 0; y < pCodecCtx->height; y++)  {
               uint8_t *p = pFrame->data[0] + y * pFrame->linesize[0];

               for (int x = 0; x < pCodecCtx->width; x++)  {
                  pixelScanCount++;
               }
            }
            av_free_packet(&packet);

         }
         else  {
            av_free_packet(&packet);
         }
      }
   }


   printf("frame = %d\n", frame);               // frame = 36395
   printf("loops = %d\n", loops);               // loops = 212127
   printf("totalFrames = %d\n", totalFrames);   // totalFrames = 154959

   delete [] buffer;
   av_free(pFrameYUV);
   av_free(pFrame);
   avcodec_close(pCodecCtx);
   avformat_close_input(&pFormatCtx);

   return 0;
}


More information about the Libav-user mailing list