Statistics
| Branch: | Revision:

ffmpeg / libavcodec / libtheoraenc.c @ 11eb3cea

History | View | Annotate | Download (9.6 KB)

1
/*
2
 * Copyright (c) 2006 Paul Richards <paul.richards@gmail.com>
3
 *
4
 * This file is part of FFmpeg.
5
 *
6
 * FFmpeg is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * FFmpeg is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with FFmpeg; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20

    
21
/*!
22
 * \file libtheoraenc.c
23
 * \brief Theora encoder using libtheora.
24
 * \author Paul Richards <paul.richards@gmail.com>
25
 *
26
 * A lot of this is copy / paste from other output codecs in
27
 * libavcodec or pure guesswork (or both).
28
 *
29
 * I have used t_ prefixes on variables which are libtheora types
30
 * and o_ prefixes on variables which are libogg types.
31
 */
32

    
33
/* FFmpeg includes */
34
#include "libavutil/intreadwrite.h"
35
#include "libavutil/log.h"
36
#include "avcodec.h"
37

    
38
/* libtheora includes */
39
#include <theora/theora.h>
40

    
41
typedef struct TheoraContext{
42
    theora_state t_state;
43
} TheoraContext;
44

    
45
/*!
46
    Concatenates an ogg_packet into the extradata.
47
*/
48
static int concatenate_packet(unsigned int* offset, AVCodecContext* avc_context, const ogg_packet* packet)
49
{
50
    const char* message = NULL;
51
    uint8_t* newdata = NULL;
52
    int newsize = avc_context->extradata_size + 2 + packet->bytes;
53

    
54
    if (packet->bytes < 0) {
55
        message = "ogg_packet has negative size";
56
    } else if (packet->bytes > 0xffff) {
57
        message = "ogg_packet is larger than 65535 bytes";
58
    } else if (newsize < avc_context->extradata_size) {
59
        message = "extradata_size would overflow";
60
    } else {
61
        newdata = av_realloc(avc_context->extradata, newsize);
62
        if (newdata == NULL)
63
            message = "av_realloc failed";
64
    }
65
    if (message != NULL) {
66
        av_log(avc_context, AV_LOG_ERROR, "concatenate_packet failed: %s\n", message);
67
        return -1;
68
    }
69

    
70
    avc_context->extradata = newdata;
71
    avc_context->extradata_size = newsize;
72
    AV_WB16(avc_context->extradata + (*offset), packet->bytes);
73
    *offset += 2;
74
    memcpy( avc_context->extradata + (*offset), packet->packet, packet->bytes );
75
    (*offset) += packet->bytes;
76
    return 0;
77
}
78

    
79
static av_cold int encode_init(AVCodecContext* avc_context)
80
{
81
    theora_info t_info;
82
    theora_comment t_comment;
83
    ogg_packet o_packet;
84
    unsigned int offset;
85
    TheoraContext *h = avc_context->priv_data;
86

    
87
    /* Set up the theora_info struct */
88
    theora_info_init( &t_info );
89
    t_info.width = FFALIGN(avc_context->width, 16);
90
    t_info.height = FFALIGN(avc_context->height, 16);
91
    t_info.frame_width = avc_context->width;
92
    t_info.frame_height = avc_context->height;
93
    t_info.offset_x = 0;
94
    t_info.offset_y = avc_context->height & 0xf;
95
    /* Swap numerator and denominator as time_base in AVCodecContext gives the
96
     * time period between frames, but theora_info needs the framerate.  */
97
    t_info.fps_numerator = avc_context->time_base.den;
98
    t_info.fps_denominator = avc_context->time_base.num;
99
    if (avc_context->sample_aspect_ratio.num != 0) {
100
        t_info.aspect_numerator = avc_context->sample_aspect_ratio.num;
101
        t_info.aspect_denominator = avc_context->sample_aspect_ratio.den;
102
    } else {
103
        t_info.aspect_numerator = 1;
104
        t_info.aspect_denominator = 1;
105
    }
106
    t_info.colorspace = OC_CS_UNSPECIFIED;
107
    t_info.pixelformat = OC_PF_420;
108
    t_info.keyframe_frequency = avc_context->gop_size;
109
    t_info.keyframe_frequency_force = avc_context->gop_size;
110
    t_info.keyframe_mindistance = avc_context->keyint_min;
111

    
112
    t_info.quick_p = 1;
113
    t_info.dropframes_p = 0;
114
    t_info.keyframe_auto_p = 1;
115
    t_info.keyframe_data_target_bitrate = t_info.target_bitrate * 1.5;
116
    t_info.keyframe_auto_threshold = 80;
117
    t_info.noise_sensitivity = 1;
118
    t_info.sharpness = 0;
119

    
120
    if (avc_context->flags & CODEC_FLAG_QSCALE) {
121
        /* to be constant with the libvorbis implementation, clip global_quality to 0 - 10
122
           Theora accepts a quality parameter p, which is:
123
                * 0 <= p <=63
124
                * an int value
125
         */
126
        t_info.quality = av_clip(avc_context->global_quality / (float)FF_QP2LAMBDA, 0, 10) * 6.3;
127
        t_info.target_bitrate = 0;
128
    } else {
129
        t_info.target_bitrate = avc_context->bit_rate;
130
        t_info.quality = 0;
131
    }
132

    
133
    /* Now initialise libtheora */
134
    if (theora_encode_init( &(h->t_state), &t_info ) != 0) {
135
        av_log(avc_context, AV_LOG_ERROR, "theora_encode_init failed\n");
136
        return -1;
137
    }
138

    
139
    /* Clear up theora_info struct */
140
    theora_info_clear( &t_info );
141

    
142
    /*
143
        Output first header packet consisting of theora
144
        header, comment, and tables.
145

146
        Each one is prefixed with a 16bit size, then they
147
        are concatenated together into ffmpeg's extradata.
148
    */
149
    offset = 0;
150

    
151
    /* Header */
152
    theora_encode_header( &(h->t_state), &o_packet );
153
    if (concatenate_packet( &offset, avc_context, &o_packet ) != 0)
154
        return -1;
155

    
156
    /* Comment */
157
    theora_comment_init( &t_comment );
158
    theora_encode_comment( &t_comment, &o_packet );
159
    if (concatenate_packet( &offset, avc_context, &o_packet ) != 0)
160
        return -1;
161
    /* Clear up theora_comment struct before we reset the packet */
162
    theora_comment_clear( &t_comment );
163
    /* And despite documentation to the contrary, theora_comment_clear
164
     * does not release the packet */
165
    ogg_packet_clear(&o_packet);
166

    
167
    /* Tables */
168
    theora_encode_tables( &(h->t_state), &o_packet );
169
    if (concatenate_packet( &offset, avc_context, &o_packet ) != 0)
170
        return -1;
171

    
172
    /* Set up the output AVFrame */
173
    avc_context->coded_frame= avcodec_alloc_frame();
174

    
175
    return 0;
176
}
177

    
178
static int encode_frame(
179
    AVCodecContext* avc_context,
180
    uint8_t *outbuf,
181
    int buf_size,
182
    void *data)
183
{
184
    yuv_buffer t_yuv_buffer;
185
    TheoraContext *h = avc_context->priv_data;
186
    AVFrame *frame = data;
187
    ogg_packet o_packet;
188
    int result;
189

    
190
    assert(avc_context->pix_fmt == PIX_FMT_YUV420P);
191

    
192
    /* Copy planes to the theora yuv_buffer */
193
    if (frame->linesize[1] != frame->linesize[2]) {
194
        av_log(avc_context, AV_LOG_ERROR, "U and V stride differ\n");
195
        return -1;
196
    }
197

    
198
    t_yuv_buffer.y_width = FFALIGN(avc_context->width, 16);
199
    t_yuv_buffer.y_height = FFALIGN(avc_context->height, 16);
200
    t_yuv_buffer.y_stride = frame->linesize[0];
201
    t_yuv_buffer.uv_width = t_yuv_buffer.y_width / 2;
202
    t_yuv_buffer.uv_height = t_yuv_buffer.y_height / 2;
203
    t_yuv_buffer.uv_stride = frame->linesize[1];
204

    
205
    t_yuv_buffer.y = frame->data[0];
206
    t_yuv_buffer.u = frame->data[1];
207
    t_yuv_buffer.v = frame->data[2];
208

    
209
    /* Now call into theora_encode_YUVin */
210
    result = theora_encode_YUVin( &(h->t_state), &t_yuv_buffer );
211
    if (result != 0) {
212
        const char* message;
213
        switch (result) {
214
            case -1:
215
                message = "differing frame sizes";
216
                break;
217
            case OC_EINVAL:
218
                message = "encoder is not ready or is finished";
219
                break;
220
            default:
221
                message = "unknown reason";
222
                break;
223
        }
224
        av_log(avc_context, AV_LOG_ERROR, "theora_encode_YUVin failed (%s) [%d]\n", message, result);
225
        return -1;
226
    }
227

    
228
    /* Pick up returned ogg_packet */
229
    result = theora_encode_packetout( &(h->t_state), 0, &o_packet );
230
    switch (result) {
231
        case 0:
232
            /* No packet is ready */
233
            return 0;
234
        case 1:
235
            /* Success, we have a packet */
236
            break;
237
        default:
238
            av_log(avc_context, AV_LOG_ERROR, "theora_encode_packetout failed [%d]\n", result);
239
            return -1;
240
    }
241

    
242
    /* Copy ogg_packet content out to buffer */
243
    if (buf_size < o_packet.bytes) {
244
        av_log(avc_context, AV_LOG_ERROR, "encoded frame too large\n");
245
        return -1;
246
    }
247
    memcpy(outbuf, o_packet.packet, o_packet.bytes);
248

    
249
    // HACK: does not take codec delay into account (neither does the decoder though)
250
    avc_context->coded_frame->pts= frame->pts;
251

    
252
    return o_packet.bytes;
253
}
254

    
255
static av_cold int encode_close(AVCodecContext* avc_context)
256
{
257
    ogg_packet o_packet;
258
    TheoraContext *h = avc_context->priv_data;
259
    int result;
260
    const char* message;
261

    
262
    result = theora_encode_packetout( &(h->t_state), 1, &o_packet );
263
    theora_clear( &(h->t_state) );
264
    av_freep(&avc_context->coded_frame);
265
    av_freep(&avc_context->extradata);
266
    avc_context->extradata_size = 0;
267

    
268
    switch (result) {
269
        case 0:/* No packet is ready */
270
        case -1:/* Encoding finished */
271
            return 0;
272
        case 1:
273
            /* We have a packet */
274
            message = "gave us a packet";
275
            break;
276
        default:
277
            message = "unknown reason";
278
            break;
279
    }
280
    av_log(avc_context, AV_LOG_ERROR, "theora_encode_packetout failed (%s) [%d]\n", message, result);
281
    return -1;
282
}
283

    
284
static const enum PixelFormat supported_pixel_formats[] = { PIX_FMT_YUV420P, PIX_FMT_NONE };
285

    
286
/*! AVCodec struct exposed to libavcodec */
287
AVCodec libtheora_encoder =
288
{
289
    .name = "libtheora",
290
    .type = CODEC_TYPE_VIDEO,
291
    .id = CODEC_ID_THEORA,
292
    .priv_data_size = sizeof(TheoraContext),
293
    .init = encode_init,
294
    .close = encode_close,
295
    .encode = encode_frame,
296
    .pix_fmts = supported_pixel_formats,
297
    .long_name = NULL_IF_CONFIG_SMALL("libtheora Theora"),
298
};