[Ffmpeg-devel] FFmpeg Theora encoding patch

Michael Niedermayer michaelni
Sat Jan 6 20:08:21 CET 2007


Hi

On Sat, Jan 06, 2007 at 03:51:28PM +0000, Paul Richards wrote:
> Hi,
> Attached is my patch to add theora encoding to ffmpeg's libavcodec (by
> using libtheora).  I am requesting help to fix the bug I mention below
> and am seeking general comments before I submit the patch properly.
> 
> Files encoded using this encoder have a problem playing in VLC.  The
> files will not play unless "Drop late frames" has been unticked in the
> advanced video settings.  Hopefully someone can tell me where this
> problem comes from.  I am not sure which API (FFmpeg or libtheora) I
> am misusing.

are these .avi or .ogg?
and does it work if you create the same theora file with another tool then
ffmpeg?
and what does "ffmpeg -v 9 -i yourfile" say?


[...]
> Index: libavcodec/theora_enc.c
> ===================================================================
> --- libavcodec/theora_enc.c	(revision 0)
> +++ libavcodec/theora_enc.c	(revision 0)
[...]
> +/**
> + * @file theora_enc.c
> + * Theora encoder using libtheora.
> + *
> + * A lot of this is copy / paste from other output codecs in
> + * libavcodec or pure guesswork (or both).
> + *
> + * I have used t_ prefixes on variables which are libtheora types
> + * and o_ prefixes on variables which are libogg types.
> + *
> + * @author Paul Richards <paul.richards at gmail.com>
> + */
> + 
> +/** FFmpeg includes */

this is not the correct doxygen syntax to cover >1 element RTFM of doxygen


> +#include "avcodec.h"
> +#include "log.h"

[...]
> +/** TheoraContext */
> +typedef struct TheoraContext{

this comment is giga useless if thats the only thing to say about it then it
would be better not to say it ...


> +    theora_state t_state;
> +} TheoraContext;
> +
> +/** Forward declares for the internal functions below */
> +static int encode_init(AVCodecContext* avctx);
> +static int encode_close(AVCodecContext* avctx);
> +static int encode_frame(AVCodecContext* avctx, uint8_t *buf, int buf_size, void *data);

always try to order code so as to avoid forward declarations ...


[...]

> +/** Internal stuff below */
> +#define NOT_IMPLEMENTED_YET 0;

?


> +
> +/**
> +    Checks that an AVCodexContext has a pixel format we understand.
> +*/
> +static int check_constraints(AVCodecContext* avc_context)
> +{
> +    /**
> +        Currently only support the following input formats:
> +        
> +        PIX_FMT_YUV420P:
> +        Planar YUV 4:2:0, 12bpp,
> +        (1 Cr & Cb sample per 2x2 Y samples).
> +    */
> +    if (avc_context->pix_fmt != PIX_FMT_YUV420P) {
> +        av_log(avc_context, AV_LOG_ERROR, "have only implemented PIX_FMT_YUV420P input");
> +        return -1;
> +    }
> +    
> +    return 0;
> +}

theres a much simpler way to achive this, and that is to set AVCodec.pix_fmts


[...]
> +    t_info.keyframe_frequency = 64;
> +    t_info.keyframe_frequency_force = 64;

AVCodecContext.gop_size


> +    t_info.keyframe_data_target_bitrate = t_info.target_bitrate * 1.5;
> +    t_info.keyframe_auto_threshold = 80;
> +    t_info.keyframe_mindistance = 8;

AVCodecContext.keyint_min


[...]
> +static int encode_frame(
> +    AVCodecContext* avc_context,
> +    uint8_t *outbuf,
> +    int buf_size,
> +    void *data)
> +{
> +    yuv_buffer t_yuv_buffer;
> +    TheoraContext *h = avc_context->priv_data;
> +    AVFrame *frame = data;
> +    ogg_packet o_packet;
> +    int result;
> +    
> +    /** Check pixel format contraints */
> +    if (check_constraints(avc_context) != 0) {
> +        return -1;
> +    }
> +        
> +    /** Copy planes to the theora yuv_buffer */

doxygen doesnt support such comments in the middle of the code i _think_
at least not last time i checked ...


[...]
> +    /** Now call into theora_encode_YUVin */
> +    result = theora_encode_YUVin( &(h->t_state), &t_yuv_buffer );
> +    switch (result) {
> +        case 0:
> +            /** Success */
> +            break;
> +        case -1:
> +            av_log(avc_context, AV_LOG_ERROR, "theora_encode_YUVin failed (differing frame sizes)\n");
> +            return -1;
> +        case OC_EINVAL:
> +            av_log(avc_context, AV_LOG_ERROR, "theora_encode_YUVin failed (encoder is not ready or is finished)\n");
> +            return -1;
> +        default:
> +            av_log(avc_context, AV_LOG_ERROR, "theora_encode_YUVin failed [%d]\n", result);
> +            return -1;
> +    }

id write

if(result){
    char *err= "?";
    if     (result==-1       ) err= "differing frame sizes";
    else if(result==OC_EINVAL) err= "encoder is not ready or is finished";
    av_log(avc_context, AV_LOG_ERROR, "theora_encode_YUVin failed [%d](%s)\n", result, err);
    return -1;
}



[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Good people do not need laws to tell them to act responsibly, while bad
people will find a way around the laws. -- Plato
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20070106/627b5ef9/attachment.pgp>



More information about the ffmpeg-devel mailing list