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

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

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

Simon Daniels
Hello,

I've come across a particular MTS file that doesn't seem to want to be decoded. I've decoded plenty of other MTS, M4V, and MOV files with my code so something seems to be unique to this one. I can play the file just fine too. Any idea what's going on here?

Here's the media info for the bad file:
General
ID                               : 0 (0x0)
Complete name                    : D:\Projects\Investigation\00793.MTS
Format                           : BDAV
Format/Info                      : Blu-ray Video
File size                        : 91.9 MiB
Duration                         : 34s 97ms
Overall bit rate                 : 22.6 Mbps
Maximum Overall bit rate         : 24.0 Mbps

Video
ID                               : 4113 (0x1011)
Menu ID                          : 1 (0x1)
Format                           : AVC
Format/Info                      : Advanced Video Codec
Format profile                   : High@L4.0
Format settings, CABAC           : No
Format settings, ReFrames        : 2 frames
Format settings, GOP             : M=1, N=28
Codec ID                         : 27
Duration                         : 33s 984ms
Bit rate mode                    : Variable
Bit rate                         : 21.4 Mbps
Maximum bit rate                 : 22.6 Mbps
Width                            : 1 920 pixels
Height                           : 1 080 pixels
Display aspect ratio             : 16:9
Frame rate                       : 29.970 fps
Color space                      : YUV
Chroma subsampling               : 4:2:0
Bit depth                        : 8 bits
Scan type                        : Interlaced
Scan order                       : Top Field First
Bits/(Pixel*Frame)               : 0.345
Stream size                      : 86.8 MiB (94%)

Audio
ID                               : 4352 (0x1100)
Menu ID                          : 1 (0x1)
Format                           : AC-3
Format/Info                      : Audio Coding 3
Mode extension                   : CM (complete main)
Codec ID                         : 129
Duration                         : 34s 16ms
Bit rate mode                    : Constant
Bit rate                         : 256 Kbps
Channel(s)                       : 2 channels
Channel positions                : Front: L R
Sampling rate                    : 48.0 KHz
Bit depth                        : 16 bits
Compression mode                 : Lossy
Delay relative to video          : -34ms
Stream size                      : 1.04 MiB (1%)

Text
ID                               : 4608 (0x1200)
Menu ID                          : 1 (0x1)
Format                           : PGS
Codec ID                         : 144
Duration                         : 33s 602ms
Delay relative to video          : -34ms



Here's a somewhat simplified version of my code. I use av_open_input_file, av_find_stream_info, avcodec_find_decoder, and avcodec_open in my helper functions.


    // Allocate video frame
    pFrame=avcodec_alloc_frame();

    // Allocate an AVFrame structure
    pFrameYUV=avcodec_alloc_frame();
    if(pFrameYUV==NULL)
    {
        return NULL;
    }
   
    // Determine required buffer size and allocate buffer
    numBytes=avpicture_get_size(PIX_FMT_YUV420P, width, height);
    buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
   
    // Assign appropriate parts of buffer to image planes in pFrameYUV
    avpicture_fill((AVPicture *)pFrameYUV, buffer, PIX_FMT_YUV420P, width, height);
   
    AVFormatContext* pFormatCtx;
    pFormatCtx = pHelper->FormatContextPointer();

    int videoStreamIndex = pHelper->VideoStreamIndex();
    int frameScanCount = 0;

    AVCodecContext* pCodecCtx;
    pCodecCtx = pHelper->CodecContextPointer();

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

       
        // Is this a packet from the video stream?
        if (packet.stream_index == videoStreamIndex &&
            frameLocation++)
        {
                       
            // Decode video frame
            avcodec_decode_video2(pCodecCtx, pFrameYUV, &isFrameFinished, &packet);

            // FOR THIS VIDEO,
isFrameFinished IS ALWAYS 0
            if (isFrameFinished == 0)
            {
                pLog->Write("Frame %d not finished", frameLocation);
            }

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

                // do some analysis on the pixels

            } // whether we successfully decoded the frame


        } // whether we were supposed to decode the frame
        
        av_free_packet(&packet);

    } // for each available frame

    //delete [] buffer;
    av_free(buffer);
    av_free(pFrame);

    // Free the YUV frame
    av_free(pFrameYUV);


Thanks!

Simon

_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Reply | Threaded
Open this post in threaded view
|

Re: got_picture_ptr of avcodec_decode_video2 always returns 0 for a particular MTS file

Andrey Utkin
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
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Reply | Threaded
Open this post in threaded view
|

Re: got_picture_ptr of avcodec_decode_video2 always returns 0 for a particular MTS file

Simon Daniels
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 <[hidden email]> 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
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user


_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Reply | Threaded
Open this post in threaded view
|

Re: got_picture_ptr of avcodec_decode_video2 always returns 0 for a particular MTS file

Simon Daniels
I updated all the deprecated functions and I'm still having the same problem.

On Mon, Feb 6, 2012 at 9:47 PM, Simon Daniels <[hidden email]> wrote:
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 <[hidden email]> 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
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user



_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Reply | Threaded
Open this post in threaded view
|

Re: got_picture_ptr of avcodec_decode_video2 always returns 0 for a particular MTS file

Andrey Utkin
2012/2/7 Simon Daniels <[hidden email]>:
> I updated all the deprecated functions and I'm still having the same
> problem.

Please share your updated code, via pastebin, and i'll take a look.

--
Andrey Utkin
_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Reply | Threaded
Open this post in threaded view
|

Re: got_picture_ptr of avcodec_decode_video2 always returns 0 for a particular MTS file

Simon Daniels
Here you go: http://pastebin.com/kKuh49ZD

Thanks!


On Tue, Feb 7, 2012 at 12:57 AM, Andrey Utkin <[hidden email]> wrote:
2012/2/7 Simon Daniels <[hidden email]>:
> I updated all the deprecated functions and I'm still having the same
> problem.

Please share your updated code, via pastebin, and i'll take a look.

--
Andrey Utkin
_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user


_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Reply | Threaded
Open this post in threaded view
|

Re: got_picture_ptr of avcodec_decode_video2 always returns 0 for a particular MTS file

Andrey Utkin
Well, i tested it, and it does decodes for me.

This is source file, which _really_ compiles and works
http://pastebin.com/ByYzePa3
And this is showdown of ffmpeg version (i used rev 08d2cee4 you
mentioned), compile and run log.
http://pastebin.com/1p22b1k8
This clearly shows that getting full frame indeed happens regularly.
So you had mistake of perception.

--
Andrey Utkin
_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Reply | Threaded
Open this post in threaded view
|

Re: got_picture_ptr of avcodec_decode_video2 always returns 0 for a particular MTS file

Simon Daniels
Ah - I think I know what's going on. In my real code, I was actually skipping over frames (intentionally). For some reason the frame that I would actually scan would never be available so I had assumed that none of them were available (my bad!).

Any idea why this video has so many frames that aren't available--return "NOT got pic". I haven't seen that with other videos I'm tried.

Thanks Andrey!




On Tue, Feb 7, 2012 at 12:05 PM, Andrey Utkin <[hidden email]> wrote:
Well, i tested it, and it does decodes for me.

This is source file, which _really_ compiles and works
http://pastebin.com/ByYzePa3
And this is showdown of ffmpeg version (i used rev 08d2cee4 you
mentioned), compile and run log.
http://pastebin.com/1p22b1k8
This clearly shows that getting full frame indeed happens regularly.
So you had mistake of perception.

--
Andrey Utkin
_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user


_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Reply | Threaded
Open this post in threaded view
|

Re: got_picture_ptr of avcodec_decode_video2 always returns 0 for a particular MTS file

Andrey Utkin
2012/2/9 Simon Daniels <[hidden email]>:
> Ah - I think I know what's going on. In my real code, I was actually
> skipping over frames (intentionally). For some reason the frame that I would
> actually scan would never be available so I had assumed that none of them
> were available (my bad!).

Pity. Next time, please... well, you get the point.

> Any idea why this video has so many frames that aren't available--return
> "NOT got pic". I haven't seen that with other videos I'm tried.

I got "NOT got pic" each second frame. In my practice it is ok.
Although i don't know what this means, you can check specific decoder
module used in your file, and find out in which cases got_picture is
set to 0.

--
Andrey Utkin
_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Reply | Threaded
Open this post in threaded view
|

Re: got_picture_ptr of avcodec_decode_video2 always returns 0 for a particular MTS file

phkarmur
Hi,

I have same problem too
Any one know how to solve this problem and what exactly problem is?

Thank you.