Mercurial > libavcodec.hg
annotate libtheoraenc.c @ 11352:6e0af2cfdcfe libavcodec
Do MC and IDCT in coding (hilbert) order
This increases the slice size to 64 pixels, due to having to decode an
entire chroma superblock row per slice.
This can be up to 6% slower depending on clip and CPU, but is necessary
for future optimizations that gain significantly more than was lost.
author | conrad |
---|---|
date | Wed, 03 Mar 2010 23:27:40 +0000 |
parents | d569841bd1b7 |
children | 8a4984c5cacc |
rev | line source |
---|---|
4403 | 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 | |
5215 | 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
4403 | 19 */ |
20 | |
21 /*! | |
8673 | 22 * \file libtheoraenc.c |
4403 | 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 */ | |
8574
d679fd3a5359
Add missing inclusion of libavutil/intreadwrite.h, fix compilation when
stefano
parents:
7040
diff
changeset
|
34 #include "libavutil/intreadwrite.h" |
6763 | 35 #include "libavutil/log.h" |
10554 | 36 #include "libavutil/base64.h" |
4403 | 37 #include "avcodec.h" |
38 | |
39 /* libtheora includes */ | |
10553 | 40 #include <theora/theoraenc.h> |
4403 | 41 |
10439 | 42 typedef struct TheoraContext { |
10553 | 43 th_enc_ctx *t_state; |
10554 | 44 uint8_t *stats; |
45 int stats_size; | |
46 int stats_offset; | |
10555
3d8ab953a869
Support 4:2:2 and 4:4:4 subsampling in libtheora encoding
conrad
parents:
10554
diff
changeset
|
47 int uv_hshift; |
3d8ab953a869
Support 4:2:2 and 4:4:4 subsampling in libtheora encoding
conrad
parents:
10554
diff
changeset
|
48 int uv_vshift; |
10679 | 49 int keyframe_mask; |
4403 | 50 } TheoraContext; |
51 | |
52 /*! | |
53 Concatenates an ogg_packet into the extradata. | |
54 */ | |
10439 | 55 static int concatenate_packet(unsigned int* offset, |
56 AVCodecContext* avc_context, | |
57 const ogg_packet* packet) | |
4403 | 58 { |
9952
4b3abcad0628
Fix "warning: assignment discards qualifiers from pointer target type"
conrad
parents:
9951
diff
changeset
|
59 const char* message = NULL; |
10439 | 60 uint8_t* newdata = NULL; |
4403 | 61 int newsize = avc_context->extradata_size + 2 + packet->bytes; |
62 | |
63 if (packet->bytes < 0) { | |
64 message = "ogg_packet has negative size"; | |
65 } else if (packet->bytes > 0xffff) { | |
66 message = "ogg_packet is larger than 65535 bytes"; | |
67 } else if (newsize < avc_context->extradata_size) { | |
68 message = "extradata_size would overflow"; | |
69 } else { | |
70 newdata = av_realloc(avc_context->extradata, newsize); | |
10444
f1ef8d3221c8
Get rid of some pointless '== NULL' / '!= 0' conditions in if statements.
diego
parents:
10439
diff
changeset
|
71 if (!newdata) |
4403 | 72 message = "av_realloc failed"; |
73 } | |
10444
f1ef8d3221c8
Get rid of some pointless '== NULL' / '!= 0' conditions in if statements.
diego
parents:
10439
diff
changeset
|
74 if (message) { |
4403 | 75 av_log(avc_context, AV_LOG_ERROR, "concatenate_packet failed: %s\n", message); |
76 return -1; | |
77 } | |
78 | |
10439 | 79 avc_context->extradata = newdata; |
4403 | 80 avc_context->extradata_size = newsize; |
5089 | 81 AV_WB16(avc_context->extradata + (*offset), packet->bytes); |
82 *offset += 2; | |
10439 | 83 memcpy(avc_context->extradata + (*offset), packet->packet, packet->bytes); |
4403 | 84 (*offset) += packet->bytes; |
85 return 0; | |
86 } | |
87 | |
10554 | 88 static int get_stats(AVCodecContext *avctx, int eos) |
89 { | |
10568
aacf5f712ba7
Support compiling against libtheora older than 1.1
conrad
parents:
10556
diff
changeset
|
90 #ifdef TH_ENCCTL_2PASS_OUT |
10554 | 91 TheoraContext *h = avctx->priv_data; |
92 uint8_t *buf; | |
93 int bytes; | |
94 | |
95 bytes = th_encode_ctl(h->t_state, TH_ENCCTL_2PASS_OUT, &buf, sizeof(buf)); | |
96 if (bytes < 0) { | |
97 av_log(avctx, AV_LOG_ERROR, "Error getting first pass stats\n"); | |
98 return -1; | |
99 } | |
100 if (!eos) { | |
101 h->stats = av_fast_realloc(h->stats, &h->stats_size, | |
102 h->stats_offset + bytes); | |
103 memcpy(h->stats + h->stats_offset, buf, bytes); | |
104 h->stats_offset += bytes; | |
105 } else { | |
106 int b64_size = ((h->stats_offset + 2) / 3) * 4 + 1; | |
107 // libtheora generates a summary header at the end | |
108 memcpy(h->stats, buf, bytes); | |
109 avctx->stats_out = av_malloc(b64_size); | |
110 av_base64_encode(avctx->stats_out, b64_size, h->stats, h->stats_offset); | |
111 } | |
112 return 0; | |
10568
aacf5f712ba7
Support compiling against libtheora older than 1.1
conrad
parents:
10556
diff
changeset
|
113 #else |
aacf5f712ba7
Support compiling against libtheora older than 1.1
conrad
parents:
10556
diff
changeset
|
114 av_log(avctx, AV_LOG_ERROR, "libtheora too old to support 2pass\n"); |
aacf5f712ba7
Support compiling against libtheora older than 1.1
conrad
parents:
10556
diff
changeset
|
115 return -1; |
aacf5f712ba7
Support compiling against libtheora older than 1.1
conrad
parents:
10556
diff
changeset
|
116 #endif |
10554 | 117 } |
118 | |
119 // libtheora won't read the entire buffer we give it at once, so we have to | |
120 // repeatedly submit it... | |
121 static int submit_stats(AVCodecContext *avctx) | |
122 { | |
10568
aacf5f712ba7
Support compiling against libtheora older than 1.1
conrad
parents:
10556
diff
changeset
|
123 #ifdef TH_ENCCTL_2PASS_IN |
10554 | 124 TheoraContext *h = avctx->priv_data; |
125 int bytes; | |
126 if (!h->stats) { | |
127 if (!avctx->stats_in) { | |
128 av_log(avctx, AV_LOG_ERROR, "No statsfile for second pass\n"); | |
129 return -1; | |
130 } | |
131 h->stats_size = strlen(avctx->stats_in) * 3/4; | |
132 h->stats = av_malloc(h->stats_size); | |
133 h->stats_size = av_base64_decode(h->stats, avctx->stats_in, h->stats_size); | |
134 } | |
135 while (h->stats_size - h->stats_offset > 0) { | |
136 bytes = th_encode_ctl(h->t_state, TH_ENCCTL_2PASS_IN, | |
137 h->stats + h->stats_offset, | |
138 h->stats_size - h->stats_offset); | |
139 if (bytes < 0) { | |
140 av_log(avctx, AV_LOG_ERROR, "Error submitting stats\n"); | |
141 return -1; | |
142 } | |
143 if (!bytes) | |
144 return 0; | |
145 h->stats_offset += bytes; | |
146 } | |
147 return 0; | |
10568
aacf5f712ba7
Support compiling against libtheora older than 1.1
conrad
parents:
10556
diff
changeset
|
148 #else |
aacf5f712ba7
Support compiling against libtheora older than 1.1
conrad
parents:
10556
diff
changeset
|
149 av_log(avctx, AV_LOG_ERROR, "libtheora too old to support 2pass\n"); |
aacf5f712ba7
Support compiling against libtheora older than 1.1
conrad
parents:
10556
diff
changeset
|
150 return -1; |
aacf5f712ba7
Support compiling against libtheora older than 1.1
conrad
parents:
10556
diff
changeset
|
151 #endif |
10554 | 152 } |
153 | |
9007
043574c5c153
Add missing av_cold in static init/close functions.
stefano
parents:
8673
diff
changeset
|
154 static av_cold int encode_init(AVCodecContext* avc_context) |
4403 | 155 { |
10553 | 156 th_info t_info; |
157 th_comment t_comment; | |
4403 | 158 ogg_packet o_packet; |
159 unsigned int offset; | |
160 TheoraContext *h = avc_context->priv_data; | |
10553 | 161 uint32_t gop_size = avc_context->gop_size; |
4403 | 162 |
163 /* Set up the theora_info struct */ | |
10553 | 164 th_info_init(&t_info); |
165 t_info.frame_width = FFALIGN(avc_context->width, 16); | |
166 t_info.frame_height = FFALIGN(avc_context->height, 16); | |
167 t_info.pic_width = avc_context->width; | |
168 t_info.pic_height = avc_context->height; | |
169 t_info.pic_x = 0; | |
170 t_info.pic_y = 0; | |
4496
a02a0d06e99b
Add a comment about swapped numerator and denominator.
diego
parents:
4403
diff
changeset
|
171 /* Swap numerator and denominator as time_base in AVCodecContext gives the |
a02a0d06e99b
Add a comment about swapped numerator and denominator.
diego
parents:
4403
diff
changeset
|
172 * time period between frames, but theora_info needs the framerate. */ |
10439 | 173 t_info.fps_numerator = avc_context->time_base.den; |
4403 | 174 t_info.fps_denominator = avc_context->time_base.num; |
10444
f1ef8d3221c8
Get rid of some pointless '== NULL' / '!= 0' conditions in if statements.
diego
parents:
10439
diff
changeset
|
175 if (avc_context->sample_aspect_ratio.num) { |
10439 | 176 t_info.aspect_numerator = avc_context->sample_aspect_ratio.num; |
4403 | 177 t_info.aspect_denominator = avc_context->sample_aspect_ratio.den; |
178 } else { | |
10439 | 179 t_info.aspect_numerator = 1; |
4403 | 180 t_info.aspect_denominator = 1; |
181 } | |
10556 | 182 |
183 if (avc_context->color_primaries == AVCOL_PRI_BT470M) | |
184 t_info.colorspace = TH_CS_ITU_REC_470M; | |
185 else if (avc_context->color_primaries == AVCOL_PRI_BT470BG) | |
186 t_info.colorspace = TH_CS_ITU_REC_470BG; | |
187 else | |
188 t_info.colorspace = TH_CS_UNSPECIFIED; | |
10555
3d8ab953a869
Support 4:2:2 and 4:4:4 subsampling in libtheora encoding
conrad
parents:
10554
diff
changeset
|
189 |
3d8ab953a869
Support 4:2:2 and 4:4:4 subsampling in libtheora encoding
conrad
parents:
10554
diff
changeset
|
190 if (avc_context->pix_fmt == PIX_FMT_YUV420P) |
3d8ab953a869
Support 4:2:2 and 4:4:4 subsampling in libtheora encoding
conrad
parents:
10554
diff
changeset
|
191 t_info.pixel_fmt = TH_PF_420; |
3d8ab953a869
Support 4:2:2 and 4:4:4 subsampling in libtheora encoding
conrad
parents:
10554
diff
changeset
|
192 else if (avc_context->pix_fmt == PIX_FMT_YUV422P) |
3d8ab953a869
Support 4:2:2 and 4:4:4 subsampling in libtheora encoding
conrad
parents:
10554
diff
changeset
|
193 t_info.pixel_fmt = TH_PF_422; |
3d8ab953a869
Support 4:2:2 and 4:4:4 subsampling in libtheora encoding
conrad
parents:
10554
diff
changeset
|
194 else if (avc_context->pix_fmt == PIX_FMT_YUV444P) |
3d8ab953a869
Support 4:2:2 and 4:4:4 subsampling in libtheora encoding
conrad
parents:
10554
diff
changeset
|
195 t_info.pixel_fmt = TH_PF_444; |
3d8ab953a869
Support 4:2:2 and 4:4:4 subsampling in libtheora encoding
conrad
parents:
10554
diff
changeset
|
196 else { |
3d8ab953a869
Support 4:2:2 and 4:4:4 subsampling in libtheora encoding
conrad
parents:
10554
diff
changeset
|
197 av_log(avc_context, AV_LOG_ERROR, "Unsupported pix_fmt\n"); |
3d8ab953a869
Support 4:2:2 and 4:4:4 subsampling in libtheora encoding
conrad
parents:
10554
diff
changeset
|
198 return -1; |
3d8ab953a869
Support 4:2:2 and 4:4:4 subsampling in libtheora encoding
conrad
parents:
10554
diff
changeset
|
199 } |
3d8ab953a869
Support 4:2:2 and 4:4:4 subsampling in libtheora encoding
conrad
parents:
10554
diff
changeset
|
200 avcodec_get_chroma_sub_sample(avc_context->pix_fmt, &h->uv_hshift, &h->uv_vshift); |
4403 | 201 |
10332 | 202 if (avc_context->flags & CODEC_FLAG_QSCALE) { |
203 /* to be constant with the libvorbis implementation, clip global_quality to 0 - 10 | |
204 Theora accepts a quality parameter p, which is: | |
205 * 0 <= p <=63 | |
206 * an int value | |
207 */ | |
10439 | 208 t_info.quality = av_clip(avc_context->global_quality / (float)FF_QP2LAMBDA, 0, 10) * 6.3; |
10332 | 209 t_info.target_bitrate = 0; |
210 } else { | |
211 t_info.target_bitrate = avc_context->bit_rate; | |
10439 | 212 t_info.quality = 0; |
10332 | 213 } |
214 | |
4403 | 215 /* Now initialise libtheora */ |
10553 | 216 h->t_state = th_encode_alloc(&t_info); |
217 if (!h->t_state) { | |
4403 | 218 av_log(avc_context, AV_LOG_ERROR, "theora_encode_init failed\n"); |
219 return -1; | |
220 } | |
221 | |
10679 | 222 h->keyframe_mask = (1 << t_info.keyframe_granule_shift) - 1; |
4403 | 223 /* Clear up theora_info struct */ |
10553 | 224 th_info_clear(&t_info); |
225 | |
226 if (th_encode_ctl(h->t_state, TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE, | |
227 &gop_size, sizeof(gop_size))) { | |
228 av_log(avc_context, AV_LOG_ERROR, "Error setting GOP size\n"); | |
229 return -1; | |
230 } | |
4403 | 231 |
10554 | 232 // need to enable 2 pass (via TH_ENCCTL_2PASS_) before encoding headers |
233 if (avc_context->flags & CODEC_FLAG_PASS1) { | |
234 if (get_stats(avc_context, 0)) | |
235 return -1; | |
236 } else if (avc_context->flags & CODEC_FLAG_PASS2) { | |
237 if (submit_stats(avc_context)) | |
238 return -1; | |
239 } | |
240 | |
4403 | 241 /* |
242 Output first header packet consisting of theora | |
243 header, comment, and tables. | |
244 | |
245 Each one is prefixed with a 16bit size, then they | |
246 are concatenated together into ffmpeg's extradata. | |
247 */ | |
248 offset = 0; | |
249 | |
10553 | 250 /* Headers */ |
251 th_comment_init(&t_comment); | |
4403 | 252 |
10553 | 253 while (th_encode_flushheader(h->t_state, &t_comment, &o_packet)) |
254 if (concatenate_packet(&offset, avc_context, &o_packet)) | |
255 return -1; | |
4403 | 256 |
10553 | 257 th_comment_clear(&t_comment); |
4403 | 258 |
259 /* Set up the output AVFrame */ | |
260 avc_context->coded_frame= avcodec_alloc_frame(); | |
261 | |
262 return 0; | |
263 } | |
264 | |
10439 | 265 static int encode_frame(AVCodecContext* avc_context, uint8_t *outbuf, |
266 int buf_size, void *data) | |
4403 | 267 { |
10553 | 268 th_ycbcr_buffer t_yuv_buffer; |
4403 | 269 TheoraContext *h = avc_context->priv_data; |
270 AVFrame *frame = data; | |
271 ogg_packet o_packet; | |
10553 | 272 int result, i; |
4403 | 273 |
10554 | 274 // EOS, finish and get 1st pass stats if applicable |
275 if (!frame) { | |
276 th_encode_packetout(h->t_state, 1, &o_packet); | |
277 if (avc_context->flags & CODEC_FLAG_PASS1) | |
278 if (get_stats(avc_context, 1)) | |
279 return -1; | |
280 return 0; | |
281 } | |
282 | |
4403 | 283 /* Copy planes to the theora yuv_buffer */ |
10553 | 284 for (i = 0; i < 3; i++) { |
10555
3d8ab953a869
Support 4:2:2 and 4:4:4 subsampling in libtheora encoding
conrad
parents:
10554
diff
changeset
|
285 t_yuv_buffer[i].width = FFALIGN(avc_context->width, 16) >> (i && h->uv_hshift); |
3d8ab953a869
Support 4:2:2 and 4:4:4 subsampling in libtheora encoding
conrad
parents:
10554
diff
changeset
|
286 t_yuv_buffer[i].height = FFALIGN(avc_context->height, 16) >> (i && h->uv_vshift); |
10553 | 287 t_yuv_buffer[i].stride = frame->linesize[i]; |
288 t_yuv_buffer[i].data = frame->data[i]; | |
4403 | 289 } |
290 | |
10554 | 291 if (avc_context->flags & CODEC_FLAG_PASS2) |
292 if (submit_stats(avc_context)) | |
293 return -1; | |
294 | |
4403 | 295 /* Now call into theora_encode_YUVin */ |
10553 | 296 result = th_encode_ycbcr_in(h->t_state, t_yuv_buffer); |
10444
f1ef8d3221c8
Get rid of some pointless '== NULL' / '!= 0' conditions in if statements.
diego
parents:
10439
diff
changeset
|
297 if (result) { |
4403 | 298 const char* message; |
299 switch (result) { | |
10439 | 300 case -1: |
301 message = "differing frame sizes"; | |
302 break; | |
10553 | 303 case TH_EINVAL: |
10439 | 304 message = "encoder is not ready or is finished"; |
305 break; | |
306 default: | |
307 message = "unknown reason"; | |
308 break; | |
4403 | 309 } |
310 av_log(avc_context, AV_LOG_ERROR, "theora_encode_YUVin failed (%s) [%d]\n", message, result); | |
311 return -1; | |
312 } | |
313 | |
10554 | 314 if (avc_context->flags & CODEC_FLAG_PASS1) |
315 if (get_stats(avc_context, 0)) | |
316 return -1; | |
317 | |
4403 | 318 /* Pick up returned ogg_packet */ |
10553 | 319 result = th_encode_packetout(h->t_state, 0, &o_packet); |
4403 | 320 switch (result) { |
10439 | 321 case 0: |
322 /* No packet is ready */ | |
323 return 0; | |
324 case 1: | |
325 /* Success, we have a packet */ | |
326 break; | |
327 default: | |
328 av_log(avc_context, AV_LOG_ERROR, "theora_encode_packetout failed [%d]\n", result); | |
329 return -1; | |
4403 | 330 } |
331 | |
332 /* Copy ogg_packet content out to buffer */ | |
333 if (buf_size < o_packet.bytes) { | |
334 av_log(avc_context, AV_LOG_ERROR, "encoded frame too large\n"); | |
335 return -1; | |
336 } | |
337 memcpy(outbuf, o_packet.packet, o_packet.bytes); | |
338 | |
10680
d569841bd1b7
Clarify comment: although still hacky, it is correct for existing libtheora
conrad
parents:
10679
diff
changeset
|
339 // HACK: assumes no encoder delay, this is true until libtheora becomes |
d569841bd1b7
Clarify comment: although still hacky, it is correct for existing libtheora
conrad
parents:
10679
diff
changeset
|
340 // multithreaded (which will be disabled unless explictly requested) |
10439 | 341 avc_context->coded_frame->pts = frame->pts; |
10679 | 342 avc_context->coded_frame->key_frame = !(o_packet.granulepos & h->keyframe_mask); |
10381
9262948fd649
Hack: set the coded frame PTS to the incoming PTS.
reimar
parents:
10332
diff
changeset
|
343 |
4403 | 344 return o_packet.bytes; |
345 } | |
346 | |
9007
043574c5c153
Add missing av_cold in static init/close functions.
stefano
parents:
8673
diff
changeset
|
347 static av_cold int encode_close(AVCodecContext* avc_context) |
4403 | 348 { |
349 TheoraContext *h = avc_context->priv_data; | |
350 | |
10553 | 351 th_encode_free(h->t_state); |
10554 | 352 av_freep(&h->stats); |
9951 | 353 av_freep(&avc_context->coded_frame); |
10554 | 354 av_freep(&avc_context->stats_out); |
9951 | 355 av_freep(&avc_context->extradata); |
356 avc_context->extradata_size = 0; | |
357 | |
10554 | 358 return 0; |
4403 | 359 } |
360 | |
361 /*! AVCodec struct exposed to libavcodec */ | |
10439 | 362 AVCodec libtheora_encoder = { |
4403 | 363 .name = "libtheora", |
364 .type = CODEC_TYPE_VIDEO, | |
365 .id = CODEC_ID_THEORA, | |
366 .priv_data_size = sizeof(TheoraContext), | |
367 .init = encode_init, | |
368 .close = encode_close, | |
369 .encode = encode_frame, | |
10554 | 370 .capabilities = CODEC_CAP_DELAY, // needed to get the statsfile summary |
10555
3d8ab953a869
Support 4:2:2 and 4:4:4 subsampling in libtheora encoding
conrad
parents:
10554
diff
changeset
|
371 .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_YUV444P, PIX_FMT_NONE}, |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6788
diff
changeset
|
372 .long_name = NULL_IF_CONFIG_SMALL("libtheora Theora"), |
4403 | 373 }; |