[Libav-user] decoding video frames

Alex Cohn alexcohn at netvision.net.il
Thu May 10 19:08:39 CEST 2012


On Thu, May 10, 2012 at 3:43 PM, Bob Self <bobslf at gmail.com> wrote:
> I'm trying to decode video frames. The decoding loop prints this message:
>      [mpeg4 @ 00823420] Invalid and inefficient vfw-avi packed B
> frames detected
>
> After that it prints these lines over and over:
>
>      [mpeg4 @ ...] slice end not reached but screenspace end (5 left
> 78000, score= -2)
>      [mpeg4 @ ...] concealing 1350 DC, 1350 AC, 1350 MV errors
>
>
> What causes these warning messages? Is this the correct way to decode video?
>
> thanks,
> Bob
>
>
> AVCodec *codec;
> AVCodecContext *codec_ctx= NULL;
> AVFormatContext *format_ctx=NULL;
> AVFrame *picture=NULL;
> int frame, got_picture, len;
> FILE *f;
> uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
> char buf[1024];
> AVPacket avpkt;
> const char *outfilename = "x.x";
> const char *filename = MOVIE;
> unsigned long frames=0L;
> int status;
> int64_t duration = 0;
> const char *cptr=NULL;
> unsigned long count=0L;
> unsigned long total_bytes = 0L;
> int vidstream = -1;
> int i;
> int flags=0;
>
> if (!exists(MOVIE))  {
>   printf("can't find %s\n", MOVIE);
>   exit 1;
> }
>
> av_log_set_flags(AV_LOG_SKIP_REPEATED);
> avcodec_register_all();
> av_register_all();
> avformat_network_init();
>
> unsigned int codec_version = avcodec_version();
> av_init_packet(&avpkt);
>
> // 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
>
>
> format_ctx = avformat_alloc_context();
> cptr = MOVIE;
> status = avformat_open_input(&format_ctx, MOVIE, NULL, NULL);
>
> if (status != 0)  {
>   printf("error1\n");
>   goto done;
> }
>
> // find the first video stream
>
> for (i=0; i<(int)format_ctx->nb_streams; i++) {
>   if (format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
>      vidstream = i;
>      break;
>   }
> }
>
> if (vidstream == -1) {
>   printf("error3\n");
>   goto done;
> }
>
> // Get a pointer to the codec context for the video stream
> codec_ctx = format_ctx->streams[vidstream]->codec;
> frames = (unsigned long)format_ctx->streams[vidstream]->nb_frames; // 154959
>
>
> double d;
>
> d = frames / 23.97; // d = 5170
> d /= 3600.0; // d = 1.79 hours
>
> memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);
>
> codec = avcodec_find_decoder(CODEC_ID_MPEG4);
> if (!codec) {
>   fprintf(stderr, "codec not found\n");
>   goto done;
> }
>
> codec_ctx = avcodec_alloc_context3(codec);
> picture= avcodec_alloc_frame();
>
> if(codec->capabilities&CODEC_CAP_TRUNCATED)  {
>   codec_ctx->flags|= CODEC_FLAG_TRUNCATED;               // we do not
> send complete frames
> }
>
> if (avcodec_open2(codec_ctx, codec, NULL) < 0) {
>   fprintf(stderr, "could not open codec\n");
>   goto done;
> }
>
> f = fopen(filename, "rb");
> if (!f) {
>   fprintf(stderr, "could not open %s\n", filename);
>   goto done;
> }
>
> frame = 0;
>
> while(1)  {
>   avpkt.size = fread(inbuf, 1, INBUF_SIZE, f);
>   count++;
>   total_bytes += avpkt.size;
>
>   if (avpkt.size == 0)  {
>      break;
>   }
>
>   avpkt.data = inbuf;
>
>   while (avpkt.size > 0) {
>      len = avcodec_decode_video2(codec_ctx, picture, &got_picture, &avpkt);
>      if (len < 0) {
>         fclose(f);
>         printf("Error while decoding frame %d, count = %ld,
> total_bytes = %ld\n", frame, count, total_bytes);
>         goto done;
>      }
>
>      if (got_picture) {
>         frame++;
>         if ((frame%100)==0)  {
>            printf("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
>    %d\n", frame);
>         }
>      }
>      avpkt.size -= len;
>      avpkt.data += len;

This code implies that the actual compressed packets are of the size
that fits precisely into INBUF_SIZE. Otherwise, when you reach the end
of first buffer you got from fread(), you will have a non-complete
packet. The decoder cannot handle such case. You should put this
remaining chunk aside and append the data you read from the file so
that the compressed packets that go to decoder are always complete.

The trick is, you don't know the actual size of the next packet,
therefore you cannot decide whether to read another piece of data from
the file, or not. This is why it is preferred to use avformat
functions to read the file.

>   }                              // while (avpkt.size > 0)
> }                                     // while(1)
>
> avpkt.data = NULL;
> avpkt.size = 0;
>
> done:
> FCLOSE(f);
>
> if (format_ctx)  {
>   //av_close_input_file(format_ctx);
>   avformat_free_context(format_ctx);
> }
> if (codec_ctx)  {
>   avcodec_close(codec_ctx);
>   av_free(codec_ctx);
> }
> if (picture)  {
>   av_free(picture);
> }

BR,
Alex Cohn


More information about the Libav-user mailing list