Statistics
| Branch: | Revision:

ffmpeg / libavcodec / libtheoraenc.c @ 3e962f31

History | View | Annotate | Download (9.08 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
    }
66
    if (message != NULL) {
67
        av_log(avc_context, AV_LOG_ERROR, "concatenate_packet failed: %s\n", message);
68
        return -1;
69
    }
70

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

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

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

    
115
    t_info.quick_p = 1;
116
    t_info.dropframes_p = 0;
117
    t_info.keyframe_auto_p = 1;
118
    t_info.keyframe_data_target_bitrate = t_info.target_bitrate * 1.5;
119
    t_info.keyframe_auto_threshold = 80;
120
    t_info.noise_sensitivity = 1;
121
    t_info.sharpness = 0;
122

    
123
    /* Now initialise libtheora */
124
    if (theora_encode_init( &(h->t_state), &t_info ) != 0) {
125
        av_log(avc_context, AV_LOG_ERROR, "theora_encode_init failed\n");
126
        return -1;
127
    }
128

    
129
    /* Clear up theora_info struct */
130
    theora_info_clear( &t_info );
131

    
132
    /*
133
        Output first header packet consisting of theora
134
        header, comment, and tables.
135

136
        Each one is prefixed with a 16bit size, then they
137
        are concatenated together into ffmpeg's extradata.
138
    */
139
    offset = 0;
140

    
141
    /* Header */
142
    theora_encode_header( &(h->t_state), &o_packet );
143
    if (concatenate_packet( &offset, avc_context, &o_packet ) != 0) {
144
        return -1;
145
    }
146

    
147
    /* Comment */
148
    theora_comment_init( &t_comment );
149
    theora_encode_comment( &t_comment, &o_packet );
150
    if (concatenate_packet( &offset, avc_context, &o_packet ) != 0) {
151
        return -1;
152
    }
153
    /* Clear up theora_comment struct before we reset the packet */
154
    theora_comment_clear( &t_comment );
155
    /* And despite documentation to the contrary, theora_comment_clear
156
     * does not release the packet */
157
    ogg_packet_clear(&o_packet);
158

    
159
    /* Tables */
160
    theora_encode_tables( &(h->t_state), &o_packet );
161
    if (concatenate_packet( &offset, avc_context, &o_packet ) != 0) {
162
        return -1;
163
    }
164

    
165
    /* Set up the output AVFrame */
166
    avc_context->coded_frame= avcodec_alloc_frame();
167

    
168
    return 0;
169
}
170

    
171
static int encode_frame(
172
    AVCodecContext* avc_context,
173
    uint8_t *outbuf,
174
    int buf_size,
175
    void *data)
176
{
177
    yuv_buffer t_yuv_buffer;
178
    TheoraContext *h = avc_context->priv_data;
179
    AVFrame *frame = data;
180
    ogg_packet o_packet;
181
    int result;
182

    
183
    assert(avc_context->pix_fmt == PIX_FMT_YUV420P);
184

    
185
    /* Copy planes to the theora yuv_buffer */
186
    if (frame->linesize[1] != frame->linesize[2]) {
187
        av_log(avc_context, AV_LOG_ERROR, "U and V stride differ\n");
188
        return -1;
189
    }
190

    
191
    t_yuv_buffer.y_width = FFALIGN(avc_context->width, 16);
192
    t_yuv_buffer.y_height = FFALIGN(avc_context->height, 16);
193
    t_yuv_buffer.y_stride = frame->linesize[0];
194
    t_yuv_buffer.uv_width = t_yuv_buffer.y_width / 2;
195
    t_yuv_buffer.uv_height = t_yuv_buffer.y_height / 2;
196
    t_yuv_buffer.uv_stride = frame->linesize[1];
197

    
198
    t_yuv_buffer.y = frame->data[0];
199
    t_yuv_buffer.u = frame->data[1];
200
    t_yuv_buffer.v = frame->data[2];
201

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

    
221
    /* Pick up returned ogg_packet */
222
    result = theora_encode_packetout( &(h->t_state), 0, &o_packet );
223
    switch (result) {
224
        case 0:
225
            /* No packet is ready */
226
            return 0;
227
        case 1:
228
            /* Success, we have a packet */
229
            break;
230
        default:
231
            av_log(avc_context, AV_LOG_ERROR, "theora_encode_packetout failed [%d]\n", result);
232
            return -1;
233
    }
234

    
235
    /* Copy ogg_packet content out to buffer */
236
    if (buf_size < o_packet.bytes) {
237
        av_log(avc_context, AV_LOG_ERROR, "encoded frame too large\n");
238
        return -1;
239
    }
240
    memcpy(outbuf, o_packet.packet, o_packet.bytes);
241

    
242
    return o_packet.bytes;
243
}
244

    
245
static av_cold int encode_close(AVCodecContext* avc_context)
246
{
247
    ogg_packet o_packet;
248
    TheoraContext *h = avc_context->priv_data;
249
    int result;
250
    const char* message;
251

    
252
    result = theora_encode_packetout( &(h->t_state), 1, &o_packet );
253
    theora_clear( &(h->t_state) );
254
    av_freep(&avc_context->coded_frame);
255
    av_freep(&avc_context->extradata);
256
    avc_context->extradata_size = 0;
257

    
258
    switch (result) {
259
        case 0:/* No packet is ready */
260
        case -1:/* Encoding finished */
261
            return 0;
262
        case 1:
263
            /* We have a packet */
264
            message = "gave us a packet";
265
            break;
266
        default:
267
            message = "unknown reason";
268
            break;
269
    }
270
    av_log(avc_context, AV_LOG_ERROR, "theora_encode_packetout failed (%s) [%d]\n", message, result);
271
    return -1;
272
}
273

    
274
static const enum PixelFormat supported_pixel_formats[] = { PIX_FMT_YUV420P, PIX_FMT_NONE };
275

    
276
/*! AVCodec struct exposed to libavcodec */
277
AVCodec libtheora_encoder =
278
{
279
    .name = "libtheora",
280
    .type = CODEC_TYPE_VIDEO,
281
    .id = CODEC_ID_THEORA,
282
    .priv_data_size = sizeof(TheoraContext),
283
    .init = encode_init,
284
    .close = encode_close,
285
    .encode = encode_frame,
286
    .pix_fmts = supported_pixel_formats,
287
    .long_name = NULL_IF_CONFIG_SMALL("libtheora Theora"),
288
};