#46 getFrameHeight mismatch after call to getVideoCodec

open
nobody
None
5
2014-08-14
2011-01-05
Elan Ruusamäe
No

i've encountered weird behavour with vp6f encoded video.

consider such test file:
<?php
$file = $argv[1];
$movie = new ffmpeg_movie($file);
printf("%s: %dx%d\n", $file, $movie->getFrameWidth(), $movie->getFrameHeight());
$movie->getVideoCodec();
printf("%s: %dx%d\n", $file, $movie->getFrameWidth(), $movie->getFrameHeight());
?>

$ php getFrameHeight-bug.php gW4LflrS.flv
[flv @ 0xcc5660]Estimating duration from bitrate, this may be inaccurate
gW4LflrS.flv: 544x306
gW4LflrS.flv: 544x320

so, after getVideoCodec has been called, the height is reported 320 instead of 306

actual size is 544x306, reported by ffmpeg -i:
$ ffmpeg -i gW4LflrS.flv
FFmpeg version 0.6.1, Copyright (c) 2000-2010 the FFmpeg developers
...
[flv @ 0x649ec0]Estimating duration from bitrate, this may be inaccurate
...
Seems stream 0 codec frame rate differs from container frame rate: 1000.00 (1000/1) -> 25.00 (25/1)
Input #0, flv, from 'gW4LflrS.flv':
Metadata:
duration : 148
width : 544
height : 306
videodatarate : 1200
canSeekToEnd : true
videocodecid : 4
audiodatarate : 160
audiocodecid : 2
framerate : 25
creationdate : Wed Oct 07 17:08:39 2009
Duration: 00:02:27.56, start: 0.000000, bitrate: 1388 kb/s
Stream #0.0: Video: vp6f, yuv420p, 544x306, 1228 kb/s, 25 tbr, 1k tbn, 1k tbc
Stream #0.1: Audio: mp3, 44100 Hz, 2 channels, s16, 160 kb/s
At least one output file must be specified
....

i've tested with various ffmpeg versions and found all reporting the same behaviour
ffmpeg-0.4.9 (segfaults)
ffmpeg-0.5.2
ffmpeg-0.6.0

php-ffmpeg-0.6.0, php-ffmpeg trunk (svn r677)

you can grab the video from here:
http://ytv.delfi.ee/v/gW4LflrS.flv
or if above fails (is mp4), then i saved copy
here: http://glen.alkohol.ee/pld/gW4LflrS.flv

Discussion

  • Elan Ruusamäe
    Elan Ruusamäe
    2011-01-05

    from code debugging it seems that avcodec_open in _php_get_decoder_context overwrites the avcodecontext

    ffmpeg_movie.c :
    static AVCodecContext* _php_get_decoder_context(ff_movie_context *ffmovie_ctx, int stream_type)
    ....
    /* open the decoder */
    if (avcodec_open(ffmovie_ctx->codec_ctx[stream_index], decoder) < 0) {
    zend_error(E_WARNING, "Could not open codec for %s", _php_get_filename(ffmovie_ctx));
    return NULL;
    }

    to use temp buffer there would solve the problem, but then calling whole method becames pointless, isn't it?

    i.e such patch:
    --- ffmpeg-php-0.6.0/ffmpeg_movie.c~ 2011-01-05 18:58:27.000000000 +0200
    +++ ffmpeg-php-0.6.0/ffmpeg_movie.c 2011-01-05 18:58:34.572647878 +0200
    @@ -510,10 +510,12 @@
    GET_CODEC_PTR(ffmovie_ctx->fmt_ctx->streams[stream_index]->codec);

    /* open the decoder */
    - if (avcodec_open(ffmovie_ctx->codec_ctx[stream_index], decoder) < 0) {
    + AVCodecContext *ctx = avcodec_alloc_context();
    + if (avcodec_open(ctx, decoder) < 0) {
    zend_error(E_WARNING, "Could not open codec for %s", _php_get_filename(ffmovie_ctx));
    return NULL;
    }
    + av_freep(&ctx);
    }
    return ffmovie_ctx->codec_ctx[stream_index];
    }