ffmpeg / libavcodec / libtheoraenc.c @ d36beb3f
History | View | Annotate | Download (12.1 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
|
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 "libavutil/base64.h" |
37 |
#include "avcodec.h" |
38 |
|
39 |
/* libtheora includes */
|
40 |
#include <theora/theoraenc.h> |
41 |
|
42 |
typedef struct TheoraContext { |
43 |
th_enc_ctx *t_state; |
44 |
uint8_t *stats; |
45 |
int stats_size;
|
46 |
int stats_offset;
|
47 |
int uv_hshift;
|
48 |
int uv_vshift;
|
49 |
int keyframe_mask;
|
50 |
} TheoraContext; |
51 |
|
52 |
/** Concatenate an ogg_packet into the extradata. */
|
53 |
static int concatenate_packet(unsigned int* offset, |
54 |
AVCodecContext* avc_context, |
55 |
const ogg_packet* packet)
|
56 |
{ |
57 |
const char* message = NULL; |
58 |
uint8_t* newdata = NULL;
|
59 |
int newsize = avc_context->extradata_size + 2 + packet->bytes; |
60 |
|
61 |
if (packet->bytes < 0) { |
62 |
message = "ogg_packet has negative size";
|
63 |
} else if (packet->bytes > 0xffff) { |
64 |
message = "ogg_packet is larger than 65535 bytes";
|
65 |
} else if (newsize < avc_context->extradata_size) { |
66 |
message = "extradata_size would overflow";
|
67 |
} else {
|
68 |
newdata = av_realloc(avc_context->extradata, newsize); |
69 |
if (!newdata)
|
70 |
message = "av_realloc failed";
|
71 |
} |
72 |
if (message) {
|
73 |
av_log(avc_context, AV_LOG_ERROR, "concatenate_packet failed: %s\n", message);
|
74 |
return -1; |
75 |
} |
76 |
|
77 |
avc_context->extradata = newdata; |
78 |
avc_context->extradata_size = newsize; |
79 |
AV_WB16(avc_context->extradata + (*offset), packet->bytes); |
80 |
*offset += 2;
|
81 |
memcpy(avc_context->extradata + (*offset), packet->packet, packet->bytes); |
82 |
(*offset) += packet->bytes; |
83 |
return 0; |
84 |
} |
85 |
|
86 |
static int get_stats(AVCodecContext *avctx, int eos) |
87 |
{ |
88 |
#ifdef TH_ENCCTL_2PASS_OUT
|
89 |
TheoraContext *h = avctx->priv_data; |
90 |
uint8_t *buf; |
91 |
int bytes;
|
92 |
|
93 |
bytes = th_encode_ctl(h->t_state, TH_ENCCTL_2PASS_OUT, &buf, sizeof(buf));
|
94 |
if (bytes < 0) { |
95 |
av_log(avctx, AV_LOG_ERROR, "Error getting first pass stats\n");
|
96 |
return -1; |
97 |
} |
98 |
if (!eos) {
|
99 |
h->stats = av_fast_realloc(h->stats, &h->stats_size, |
100 |
h->stats_offset + bytes); |
101 |
memcpy(h->stats + h->stats_offset, buf, bytes); |
102 |
h->stats_offset += bytes; |
103 |
} else {
|
104 |
int b64_size = AV_BASE64_SIZE(h->stats_offset);
|
105 |
// libtheora generates a summary header at the end
|
106 |
memcpy(h->stats, buf, bytes); |
107 |
avctx->stats_out = av_malloc(b64_size); |
108 |
av_base64_encode(avctx->stats_out, b64_size, h->stats, h->stats_offset); |
109 |
} |
110 |
return 0; |
111 |
#else
|
112 |
av_log(avctx, AV_LOG_ERROR, "libtheora too old to support 2pass\n");
|
113 |
return -1; |
114 |
#endif
|
115 |
} |
116 |
|
117 |
// libtheora won't read the entire buffer we give it at once, so we have to
|
118 |
// repeatedly submit it...
|
119 |
static int submit_stats(AVCodecContext *avctx) |
120 |
{ |
121 |
#ifdef TH_ENCCTL_2PASS_IN
|
122 |
TheoraContext *h = avctx->priv_data; |
123 |
int bytes;
|
124 |
if (!h->stats) {
|
125 |
if (!avctx->stats_in) {
|
126 |
av_log(avctx, AV_LOG_ERROR, "No statsfile for second pass\n");
|
127 |
return -1; |
128 |
} |
129 |
h->stats_size = strlen(avctx->stats_in) * 3/4; |
130 |
h->stats = av_malloc(h->stats_size); |
131 |
h->stats_size = av_base64_decode(h->stats, avctx->stats_in, h->stats_size); |
132 |
} |
133 |
while (h->stats_size - h->stats_offset > 0) { |
134 |
bytes = th_encode_ctl(h->t_state, TH_ENCCTL_2PASS_IN, |
135 |
h->stats + h->stats_offset, |
136 |
h->stats_size - h->stats_offset); |
137 |
if (bytes < 0) { |
138 |
av_log(avctx, AV_LOG_ERROR, "Error submitting stats\n");
|
139 |
return -1; |
140 |
} |
141 |
if (!bytes)
|
142 |
return 0; |
143 |
h->stats_offset += bytes; |
144 |
} |
145 |
return 0; |
146 |
#else
|
147 |
av_log(avctx, AV_LOG_ERROR, "libtheora too old to support 2pass\n");
|
148 |
return -1; |
149 |
#endif
|
150 |
} |
151 |
|
152 |
static av_cold int encode_init(AVCodecContext* avc_context) |
153 |
{ |
154 |
th_info t_info; |
155 |
th_comment t_comment; |
156 |
ogg_packet o_packet; |
157 |
unsigned int offset; |
158 |
TheoraContext *h = avc_context->priv_data; |
159 |
uint32_t gop_size = avc_context->gop_size; |
160 |
|
161 |
/* Set up the theora_info struct */
|
162 |
th_info_init(&t_info); |
163 |
t_info.frame_width = FFALIGN(avc_context->width, 16);
|
164 |
t_info.frame_height = FFALIGN(avc_context->height, 16);
|
165 |
t_info.pic_width = avc_context->width; |
166 |
t_info.pic_height = avc_context->height; |
167 |
t_info.pic_x = 0;
|
168 |
t_info.pic_y = 0;
|
169 |
/* Swap numerator and denominator as time_base in AVCodecContext gives the
|
170 |
* time period between frames, but theora_info needs the framerate. */
|
171 |
t_info.fps_numerator = avc_context->time_base.den; |
172 |
t_info.fps_denominator = avc_context->time_base.num; |
173 |
if (avc_context->sample_aspect_ratio.num) {
|
174 |
t_info.aspect_numerator = avc_context->sample_aspect_ratio.num; |
175 |
t_info.aspect_denominator = avc_context->sample_aspect_ratio.den; |
176 |
} else {
|
177 |
t_info.aspect_numerator = 1;
|
178 |
t_info.aspect_denominator = 1;
|
179 |
} |
180 |
|
181 |
if (avc_context->color_primaries == AVCOL_PRI_BT470M)
|
182 |
t_info.colorspace = TH_CS_ITU_REC_470M; |
183 |
else if (avc_context->color_primaries == AVCOL_PRI_BT470BG) |
184 |
t_info.colorspace = TH_CS_ITU_REC_470BG; |
185 |
else
|
186 |
t_info.colorspace = TH_CS_UNSPECIFIED; |
187 |
|
188 |
if (avc_context->pix_fmt == PIX_FMT_YUV420P)
|
189 |
t_info.pixel_fmt = TH_PF_420; |
190 |
else if (avc_context->pix_fmt == PIX_FMT_YUV422P) |
191 |
t_info.pixel_fmt = TH_PF_422; |
192 |
else if (avc_context->pix_fmt == PIX_FMT_YUV444P) |
193 |
t_info.pixel_fmt = TH_PF_444; |
194 |
else {
|
195 |
av_log(avc_context, AV_LOG_ERROR, "Unsupported pix_fmt\n");
|
196 |
return -1; |
197 |
} |
198 |
avcodec_get_chroma_sub_sample(avc_context->pix_fmt, &h->uv_hshift, &h->uv_vshift); |
199 |
|
200 |
if (avc_context->flags & CODEC_FLAG_QSCALE) {
|
201 |
/* to be constant with the libvorbis implementation, clip global_quality to 0 - 10
|
202 |
Theora accepts a quality parameter p, which is:
|
203 |
* 0 <= p <=63
|
204 |
* an int value
|
205 |
*/
|
206 |
t_info.quality = av_clip(avc_context->global_quality / (float)FF_QP2LAMBDA, 0, 10) * 6.3; |
207 |
t_info.target_bitrate = 0;
|
208 |
} else {
|
209 |
t_info.target_bitrate = avc_context->bit_rate; |
210 |
t_info.quality = 0;
|
211 |
} |
212 |
|
213 |
/* Now initialise libtheora */
|
214 |
h->t_state = th_encode_alloc(&t_info); |
215 |
if (!h->t_state) {
|
216 |
av_log(avc_context, AV_LOG_ERROR, "theora_encode_init failed\n");
|
217 |
return -1; |
218 |
} |
219 |
|
220 |
h->keyframe_mask = (1 << t_info.keyframe_granule_shift) - 1; |
221 |
/* Clear up theora_info struct */
|
222 |
th_info_clear(&t_info); |
223 |
|
224 |
if (th_encode_ctl(h->t_state, TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE,
|
225 |
&gop_size, sizeof(gop_size))) {
|
226 |
av_log(avc_context, AV_LOG_ERROR, "Error setting GOP size\n");
|
227 |
return -1; |
228 |
} |
229 |
|
230 |
// need to enable 2 pass (via TH_ENCCTL_2PASS_) before encoding headers
|
231 |
if (avc_context->flags & CODEC_FLAG_PASS1) {
|
232 |
if (get_stats(avc_context, 0)) |
233 |
return -1; |
234 |
} else if (avc_context->flags & CODEC_FLAG_PASS2) { |
235 |
if (submit_stats(avc_context))
|
236 |
return -1; |
237 |
} |
238 |
|
239 |
/*
|
240 |
Output first header packet consisting of theora
|
241 |
header, comment, and tables.
|
242 |
|
243 |
Each one is prefixed with a 16bit size, then they
|
244 |
are concatenated together into ffmpeg's extradata.
|
245 |
*/
|
246 |
offset = 0;
|
247 |
|
248 |
/* Headers */
|
249 |
th_comment_init(&t_comment); |
250 |
|
251 |
while (th_encode_flushheader(h->t_state, &t_comment, &o_packet))
|
252 |
if (concatenate_packet(&offset, avc_context, &o_packet))
|
253 |
return -1; |
254 |
|
255 |
th_comment_clear(&t_comment); |
256 |
|
257 |
/* Set up the output AVFrame */
|
258 |
avc_context->coded_frame= avcodec_alloc_frame(); |
259 |
|
260 |
return 0; |
261 |
} |
262 |
|
263 |
static int encode_frame(AVCodecContext* avc_context, uint8_t *outbuf, |
264 |
int buf_size, void *data) |
265 |
{ |
266 |
th_ycbcr_buffer t_yuv_buffer; |
267 |
TheoraContext *h = avc_context->priv_data; |
268 |
AVFrame *frame = data; |
269 |
ogg_packet o_packet; |
270 |
int result, i;
|
271 |
|
272 |
// EOS, finish and get 1st pass stats if applicable
|
273 |
if (!frame) {
|
274 |
th_encode_packetout(h->t_state, 1, &o_packet);
|
275 |
if (avc_context->flags & CODEC_FLAG_PASS1)
|
276 |
if (get_stats(avc_context, 1)) |
277 |
return -1; |
278 |
return 0; |
279 |
} |
280 |
|
281 |
/* Copy planes to the theora yuv_buffer */
|
282 |
for (i = 0; i < 3; i++) { |
283 |
t_yuv_buffer[i].width = FFALIGN(avc_context->width, 16) >> (i && h->uv_hshift);
|
284 |
t_yuv_buffer[i].height = FFALIGN(avc_context->height, 16) >> (i && h->uv_vshift);
|
285 |
t_yuv_buffer[i].stride = frame->linesize[i]; |
286 |
t_yuv_buffer[i].data = frame->data[i]; |
287 |
} |
288 |
|
289 |
if (avc_context->flags & CODEC_FLAG_PASS2)
|
290 |
if (submit_stats(avc_context))
|
291 |
return -1; |
292 |
|
293 |
/* Now call into theora_encode_YUVin */
|
294 |
result = th_encode_ycbcr_in(h->t_state, t_yuv_buffer); |
295 |
if (result) {
|
296 |
const char* message; |
297 |
switch (result) {
|
298 |
case -1: |
299 |
message = "differing frame sizes";
|
300 |
break;
|
301 |
case TH_EINVAL:
|
302 |
message = "encoder is not ready or is finished";
|
303 |
break;
|
304 |
default:
|
305 |
message = "unknown reason";
|
306 |
break;
|
307 |
} |
308 |
av_log(avc_context, AV_LOG_ERROR, "theora_encode_YUVin failed (%s) [%d]\n", message, result);
|
309 |
return -1; |
310 |
} |
311 |
|
312 |
if (avc_context->flags & CODEC_FLAG_PASS1)
|
313 |
if (get_stats(avc_context, 0)) |
314 |
return -1; |
315 |
|
316 |
/* Pick up returned ogg_packet */
|
317 |
result = th_encode_packetout(h->t_state, 0, &o_packet);
|
318 |
switch (result) {
|
319 |
case 0: |
320 |
/* No packet is ready */
|
321 |
return 0; |
322 |
case 1: |
323 |
/* Success, we have a packet */
|
324 |
break;
|
325 |
default:
|
326 |
av_log(avc_context, AV_LOG_ERROR, "theora_encode_packetout failed [%d]\n", result);
|
327 |
return -1; |
328 |
} |
329 |
|
330 |
/* Copy ogg_packet content out to buffer */
|
331 |
if (buf_size < o_packet.bytes) {
|
332 |
av_log(avc_context, AV_LOG_ERROR, "encoded frame too large\n");
|
333 |
return -1; |
334 |
} |
335 |
memcpy(outbuf, o_packet.packet, o_packet.bytes); |
336 |
|
337 |
// HACK: assumes no encoder delay, this is true until libtheora becomes
|
338 |
// multithreaded (which will be disabled unless explictly requested)
|
339 |
avc_context->coded_frame->pts = frame->pts; |
340 |
avc_context->coded_frame->key_frame = !(o_packet.granulepos & h->keyframe_mask); |
341 |
|
342 |
return o_packet.bytes;
|
343 |
} |
344 |
|
345 |
static av_cold int encode_close(AVCodecContext* avc_context) |
346 |
{ |
347 |
TheoraContext *h = avc_context->priv_data; |
348 |
|
349 |
th_encode_free(h->t_state); |
350 |
av_freep(&h->stats); |
351 |
av_freep(&avc_context->coded_frame); |
352 |
av_freep(&avc_context->stats_out); |
353 |
av_freep(&avc_context->extradata); |
354 |
avc_context->extradata_size = 0;
|
355 |
|
356 |
return 0; |
357 |
} |
358 |
|
359 |
/** AVCodec struct exposed to libavcodec */
|
360 |
AVCodec ff_libtheora_encoder = { |
361 |
.name = "libtheora",
|
362 |
.type = AVMEDIA_TYPE_VIDEO, |
363 |
.id = CODEC_ID_THEORA, |
364 |
.priv_data_size = sizeof(TheoraContext),
|
365 |
.init = encode_init, |
366 |
.close = encode_close, |
367 |
.encode = encode_frame, |
368 |
.capabilities = CODEC_CAP_DELAY, // needed to get the statsfile summary
|
369 |
.pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_YUV444P, PIX_FMT_NONE}, |
370 |
.long_name = NULL_IF_CONFIG_SMALL("libtheora Theora"),
|
371 |
}; |