[Libav-user] got_picture_ptr of avcodec_decode_video2 always returns 0 for a particular MTS file

Simon Daniels simondaniels23 at gmail.com
Tue Feb 7 06:47:33 CET 2012


Hi Andrey,

Thanks for the help!

1. Lib versions: Using the shared library and my code below, I tried 0.8.3
(PC) and 08d2cee4 (Mac) and could not scan the file. However, I tried the
static executable of 0.8 and 0.10 on Mac and I *could* transcode it to MP4.

2. Link to video (it's almost 2gb):
http://dl.dropbox.com/u/28441949/00793.MTS

3. Simplified, but compilable source code:

int Scan(const char *inputfile)
{

    totalFrames = 0;
    frameLocation = 0;

    AVFormatContext *pFormatCtx;
    unsigned int    i, videoStream;
    AVCodecContext  *pCodecCtx;
    AVCodec         *pCodec;
    AVFrame         *pFrame;
    AVFrame         *pFrameYUV;
    int             numBytes;
    uint8_t         *buffer;

    clock_t start = clock();

    // Register all formats and codecs
    av_register_all();

    // Open video file
    if(av_open_input_file(&pFormatCtx, inputfile, NULL, 0, NULL)!=0)
    {
        return -1; // Couldn't open file
    }

    // Retrieve stream information
    if(av_find_stream_info(pFormatCtx)<0)
    {
        return -2; // Couldn't find stream information
    }

    // Dump information about file onto standard error
    dump_format(pFormatCtx, 0, inputfile, false);

    // Find the first video stream
    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; // Didn't find a video stream
    }

    // Get a pointer to the codec context for the video stream
    pCodecCtx = pFormatCtx->streams[videoStream]->codec;

    // get duration
    double duration = double(pFormatCtx->duration) / AV_TIME_BASE;
    cout << "Video duration: " << duration << std::endl;

    // Find the decoder for the video stream
    pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
    if(pCodec==NULL)
    {
        return -4; // Codec not found
    }

    // Inform the codec that we can handle truncated bitstreams -- i.e.,
    // bitstreams where frame boundaries can fall in the middle of packets
    if(pCodec->capabilities & CODEC_CAP_TRUNCATED)
        pCodecCtx->flags|=CODEC_FLAG_TRUNCATED;

    // Open codec
    if(avcodec_open(pCodecCtx, pCodec)<0)
    {
        return -5; // Could not open codec
    }

    std::cout << "Using codec: " << pCodec->name << std::endl;

    // Allocate video frame
    pFrame=avcodec_alloc_frame();

    // Allocate an AVFrame structure
    pFrameYUV=avcodec_alloc_frame();
    if(pFrameYUV==NULL)
    {
        return -6;
    }

    // Determine required buffer size and allocate buffer
    // originally:  PIX_FMT_RGB24
    numBytes=avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width,
pCodecCtx->height);
    buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));

    // Assign appropriate parts of buffer to image planes in pFrameRGB
    // originally:  PIX_FMT_RGB24
    avpicture_fill((AVPicture *)pFrameYUV, buffer, PIX_FMT_YUV420P,
        pCodecCtx->width, pCodecCtx->height);

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

    AVPacket packet;
    int isFrameFinished = 0;

    int pixelScanCount = 0;

    std::cout << "videoWidth = " << pCodecCtx->width << std::endl;
    std::cout << "videoHeight = " << pCodecCtx->height << std::endl;

    while (av_read_frame(pFormatCtx, &packet) >= 0)
    {

        // Is this a packet from the video stream?
        if (packet.stream_index == videoStream &&
            frameLocation++ % frameSkip == 0)
        {
            // Decode video frame

            avcodec_decode_video2(pCodecCtx, pFrame, &isFrameFinished,
&packet);

            // Did we get a video frame?
            if (isFrameFinished) {

                // SCANNING GOES HERE
                pixelScanCount = 0;

                for (int y = 0; y < pCodecCtx->height; y++)
                {
                    uint8_t *p = pFrame->data[0] + y * pFrame->linesize[0];
// this gets Y' in YUV

                    for (int x = 0; x < pCodecCtx->width; x++)
                    {

                        pixelScanCount++;

                        //printf("Frame %d at %d, %d has Y'=%d\n",
frameLocation, x, y, p[x]);
                    }

                }

                av_free_packet(&packet);

            }
            else // frame isn't finished. not sure why we'd hit this
            {
                av_free_packet(&packet);
            }


        }

    }

    delete [] buffer;
    av_free(pFrameYUV);

    // Free the YUV frame
    av_free(pFrame);

    // Close the codec
    avcodec_close(pCodecCtx);

    // Close the video file
    av_close_input_file(pFormatCtx);
}


4. When I enabled av_log_set_level(AV_LOG_DEBUG) in my app, I saw several
of these:
[h264 @ 09FC0940] Frame num gap 10 8
[h264 @ 09FC0940] Frame num gap 15 12
[h264 @ 09FC0940] Frame num gap 15 13
[h264 @ 09FC0940] Frame num gap 20 17
...


So considering the fact that the command-line utility was able to
transcode, I'm assuming there's something wrong in my code. I've seen some
warnings for deprecated functions so maybe that's my problem?

Thanks!

Simon





On Mon, Feb 6, 2012 at 2:56 AM, Andrey Utkin <andrey.krieger.utkin at gmail.com
> wrote:

> Please help us help you - provide
> - version of libs you use
> - compilable minimized source code of your app
> - this sample file
>
> BTW, did you try to transcode it with ffmpeg command-line utility? If
> it also fails, please provide its full output with -loglevel debug
> BTW2 try to av_log_set_level(AV_LOG_DEBUG); in your app - maybe you'll
> see useful messages on stderr.
>
>
> --
> Andrey Utkin
> _______________________________________________
> Libav-user mailing list
> Libav-user at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/libav-user
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20120206/a0a13ad3/attachment.html>


More information about the Libav-user mailing list