[FFmpeg-devel] [PATCH] Support playing SMV files.

Reimar Döffinger Reimar.Doeffinger at gmx.de
Tue Oct 2 21:17:35 CEST 2012


On Tue, Oct 02, 2012 at 11:50:08AM +0100, Ash Hughes wrote:
> +            vst->codec->extradata_size = sizeof(SMVCodecExtra);
> +            vst->codec->extradata = av_malloc(sizeof(SMVCodecExtra) + FF_INPUT_BUFFER_PADDING_SIZE);

You can't store extradata directly like that, if you were to mux
it like that in a container on a little-endian machine the resulting
file would only be readable on a little-endian machine again.
And that is not even going into issues like struct alignment which
could break things even when just changing compilers.

> @@ -617,9 +625,14 @@
>              if (ret < 0)
>                  goto smv_out;
>              pkt->pos -= 3;
> -            pkt->pts = wav->smv_block * wav->smv_frames_per_jpeg;
> -            wav->smv_block++;
> +            pkt->pts = wav->smv_block * wav->smv_frames_per_jpeg + wav->smv_cur_pt;
> +            wav->smv_cur_pt++;
> +            wav->smv_cur_pt %= wav->smv_frames_per_jpeg;
> +            if (wav->smv_cur_pt == 0)
> +                wav->smv_block++;

Are you trying to create one packet per final frame here?
I don't think that should be done, IMHO it complicates things
without much benefit.

> +    s->picture[0].reference = s->picture[1].reference = 3;
> +    s->picture[2].reference = 3;

Why? SMV doesn't use reference frames to my knowledge.

> +    s->avctx[0] = avctx;
> +    s->avctx[1] = avcodec_alloc_context3(s->codec);

You never actually use s->avctx[0]

> +int ff_smvjpeg_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
> +                          AVPacket *avpkt)

The indentation seems a bit strange.

> +{    

Trailing whitespace can't be committed into the repository.

> +    SMVJpegDecodeContext *s = avctx->priv_data;
> +    int ret = 0;
> +    AVFrame* buf_data = &s->picture[2];
> +    AVFrame* mjpeg_data = &s->picture[0];
> +    AVFrame* output = data;
> +    int u;
> +    int cur_frame = avpkt->pts % s->frames_per_jpeg;
> +    int* force_decode = (int*)avpkt->priv;

I don't think you're supposed to use "priv" that way, it won't
work in any external players like MPlayer or VLC.
You could use side data, but as said I think this approach is wrong.
There should be only one packet per frames_per_jpeg frames.
The decoder will then return 0 for all but the first frame to produce
multiple frames from one input packet.
I suspect this is likely to uncover some bugs though.

> +        /* we can't open or close the codec in init or end so we have
> +           to do it all here. */

Why?
Also opening/closing the codec is potentially slow, so it really should
not be done each time.

> +            av_picture_copy((AVPicture*)&s->picture[2], (AVPicture*)mjpeg_data,
> +                s->pix_fmt, buf_data->width, buf_data->height);
> +    av_image_copy_skip(&s->picture[1].data, &s->picture[1].linesize,
> +        buf_data->data, buf_data->linesize, avctx->pix_fmt, avctx->width,
> +        avctx->height, cur_frame);

This is 2 copies more than what should be necessary.
The first obviously can be avoided by fixing things so you can
open/close the JPEG decoder in the open/close decoder functions.
The second can be avoided by not setting CODEC_CAP_DR1 and just
exporting the appropriate part of the decoded frame.
The whole point of CODEC_CAP_DR1 is to avoid copying, if you
end up doing a copy in the codec because of it you do the opposite
of what its purpose it.
You are by far not the only one to misunderstand this (well, I assume
you misunderstood it), so suggestions for documenting this better
are welcome.

> +    if (s->picture[2].data[0]) {
> +        av_freep(&s->picture[2].data[0]);
> +    }

The if() is unnecessary.


More information about the ffmpeg-devel mailing list