Mercurial > libavcodec.hg
annotate libtheoraenc.c @ 12043:f9a0bd0888a4 libavcodec
mpegaudio: call ff_mpegaudiodec_init_mmx() only from float decoder
The mmx code is floating-point only, and this function does not know
from which decoder it is called. Without this change, the integer
decoder only "works" because the size of the context struct is smaller
in this case, and the mmx init function writes the function pointer
outside the allocated context.
author | mru |
---|---|
date | Thu, 01 Jul 2010 23:21:17 +0000 |
parents | fdafbcef52f5 |
children |
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 | |
11643
92236ee7be0f
cosmetics: Switch Doxygen comments to JavaDoc style.
diego
parents:
11560
diff
changeset
|
21 /** |
11644
7dd2a45249a9
Remove explicit filename from Doxygen @file commands.
diego
parents:
11643
diff
changeset
|
22 * @file |
11643
92236ee7be0f
cosmetics: Switch Doxygen comments to JavaDoc style.
diego
parents:
11560
diff
changeset
|
23 * @brief Theora encoder using libtheora. |
92236ee7be0f
cosmetics: Switch Doxygen comments to JavaDoc style.
diego
parents:
11560
diff
changeset
|
24 * @author Paul Richards <paul.richards@gmail.com> |
4403 | 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 | |
12024 | 52 /** Concatenate an ogg_packet into the extradata. */ |
10439 | 53 static int concatenate_packet(unsigned int* offset, |
54 AVCodecContext* avc_context, | |
55 const ogg_packet* packet) | |
4403 | 56 { |
9952
4b3abcad0628
Fix "warning: assignment discards qualifiers from pointer target type"
conrad
parents:
9951
diff
changeset
|
57 const char* message = NULL; |
10439 | 58 uint8_t* newdata = NULL; |
4403 | 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); | |
10444
f1ef8d3221c8
Get rid of some pointless '== NULL' / '!= 0' conditions in if statements.
diego
parents:
10439
diff
changeset
|
69 if (!newdata) |
4403 | 70 message = "av_realloc failed"; |
71 } | |
10444
f1ef8d3221c8
Get rid of some pointless '== NULL' / '!= 0' conditions in if statements.
diego
parents:
10439
diff
changeset
|
72 if (message) { |
4403 | 73 av_log(avc_context, AV_LOG_ERROR, "concatenate_packet failed: %s\n", message); |
74 return -1; | |
75 } | |
76 | |
10439 | 77 avc_context->extradata = newdata; |
4403 | 78 avc_context->extradata_size = newsize; |
5089 | 79 AV_WB16(avc_context->extradata + (*offset), packet->bytes); |
80 *offset += 2; | |
10439 | 81 memcpy(avc_context->extradata + (*offset), packet->packet, packet->bytes); |
4403 | 82 (*offset) += packet->bytes; |
83 return 0; | |
84 } | |
85 | |
10554 | 86 static int get_stats(AVCodecContext *avctx, int eos) |
87 { | |
10568
aacf5f712ba7
Support compiling against libtheora older than 1.1
conrad
parents:
10556
diff
changeset
|
88 #ifdef TH_ENCCTL_2PASS_OUT |
10554 | 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 { | |
11825 | 104 int b64_size = AV_BASE64_SIZE(h->stats_offset); |
10554 | 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; | |
10568
aacf5f712ba7
Support compiling against libtheora older than 1.1
conrad
parents:
10556
diff
changeset
|
111 #else |
aacf5f712ba7
Support compiling against libtheora older than 1.1
conrad
parents:
10556
diff
changeset
|
112 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
|
113 return -1; |
aacf5f712ba7
Support compiling against libtheora older than 1.1
conrad
parents:
10556
diff
changeset
|
114 #endif |
10554 | 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 { | |
10568
aacf5f712ba7
Support compiling against libtheora older than 1.1
conrad
parents:
10556
diff
changeset
|
121 #ifdef TH_ENCCTL_2PASS_IN |
10554 | 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; | |
10568
aacf5f712ba7
Support compiling against libtheora older than 1.1
conrad
parents:
10556
diff
changeset
|
146 #else |
aacf5f712ba7
Support compiling against libtheora older than 1.1
conrad
parents:
10556
diff
changeset
|
147 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
|
148 return -1; |
aacf5f712ba7
Support compiling against libtheora older than 1.1
conrad
parents:
10556
diff
changeset
|
149 #endif |
10554 | 150 } |
151 | |
9007
043574c5c153
Add missing av_cold in static init/close functions.
stefano
parents:
8673
diff
changeset
|
152 static av_cold int encode_init(AVCodecContext* avc_context) |
4403 | 153 { |
10553 | 154 th_info t_info; |
155 th_comment t_comment; | |
4403 | 156 ogg_packet o_packet; |
157 unsigned int offset; | |
158 TheoraContext *h = avc_context->priv_data; | |
10553 | 159 uint32_t gop_size = avc_context->gop_size; |
4403 | 160 |
161 /* Set up the theora_info struct */ | |
10553 | 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; | |
4496
a02a0d06e99b
Add a comment about swapped numerator and denominator.
diego
parents:
4403
diff
changeset
|
169 /* 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
|
170 * time period between frames, but theora_info needs the framerate. */ |
10439 | 171 t_info.fps_numerator = avc_context->time_base.den; |
4403 | 172 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
|
173 if (avc_context->sample_aspect_ratio.num) { |
10439 | 174 t_info.aspect_numerator = avc_context->sample_aspect_ratio.num; |
4403 | 175 t_info.aspect_denominator = avc_context->sample_aspect_ratio.den; |
176 } else { | |
10439 | 177 t_info.aspect_numerator = 1; |
4403 | 178 t_info.aspect_denominator = 1; |
179 } | |
10556 | 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; | |
10555
3d8ab953a869
Support 4:2:2 and 4:4:4 subsampling in libtheora encoding
conrad
parents:
10554
diff
changeset
|
187 |
3d8ab953a869
Support 4:2:2 and 4:4:4 subsampling in libtheora encoding
conrad
parents:
10554
diff
changeset
|
188 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
|
189 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
|
190 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
|
191 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
|
192 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
|
193 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
|
194 else { |
3d8ab953a869
Support 4:2:2 and 4:4:4 subsampling in libtheora encoding
conrad
parents:
10554
diff
changeset
|
195 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
|
196 return -1; |
3d8ab953a869
Support 4:2:2 and 4:4:4 subsampling in libtheora encoding
conrad
parents:
10554
diff
changeset
|
197 } |
3d8ab953a869
Support 4:2:2 and 4:4:4 subsampling in libtheora encoding
conrad
parents:
10554
diff
changeset
|
198 avcodec_get_chroma_sub_sample(avc_context->pix_fmt, &h->uv_hshift, &h->uv_vshift); |
4403 | 199 |
10332 | 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 */ | |
10439 | 206 t_info.quality = av_clip(avc_context->global_quality / (float)FF_QP2LAMBDA, 0, 10) * 6.3; |
10332 | 207 t_info.target_bitrate = 0; |
208 } else { | |
209 t_info.target_bitrate = avc_context->bit_rate; | |
10439 | 210 t_info.quality = 0; |
10332 | 211 } |
212 | |
4403 | 213 /* Now initialise libtheora */ |
10553 | 214 h->t_state = th_encode_alloc(&t_info); |
215 if (!h->t_state) { | |
4403 | 216 av_log(avc_context, AV_LOG_ERROR, "theora_encode_init failed\n"); |
217 return -1; | |
218 } | |
219 | |
10679 | 220 h->keyframe_mask = (1 << t_info.keyframe_granule_shift) - 1; |
4403 | 221 /* Clear up theora_info struct */ |
10553 | 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 } | |
4403 | 229 |
10554 | 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 | |
4403 | 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 | |
10553 | 248 /* Headers */ |
249 th_comment_init(&t_comment); | |
4403 | 250 |
10553 | 251 while (th_encode_flushheader(h->t_state, &t_comment, &o_packet)) |
252 if (concatenate_packet(&offset, avc_context, &o_packet)) | |
253 return -1; | |
4403 | 254 |
10553 | 255 th_comment_clear(&t_comment); |
4403 | 256 |
257 /* Set up the output AVFrame */ | |
258 avc_context->coded_frame= avcodec_alloc_frame(); | |
259 | |
260 return 0; | |
261 } | |
262 | |
10439 | 263 static int encode_frame(AVCodecContext* avc_context, uint8_t *outbuf, |
264 int buf_size, void *data) | |
4403 | 265 { |
10553 | 266 th_ycbcr_buffer t_yuv_buffer; |
4403 | 267 TheoraContext *h = avc_context->priv_data; |
268 AVFrame *frame = data; | |
269 ogg_packet o_packet; | |
10553 | 270 int result, i; |
4403 | 271 |
10554 | 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 | |
4403 | 281 /* Copy planes to the theora yuv_buffer */ |
10553 | 282 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
|
283 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
|
284 t_yuv_buffer[i].height = FFALIGN(avc_context->height, 16) >> (i && h->uv_vshift); |
10553 | 285 t_yuv_buffer[i].stride = frame->linesize[i]; |
286 t_yuv_buffer[i].data = frame->data[i]; | |
4403 | 287 } |
288 | |
10554 | 289 if (avc_context->flags & CODEC_FLAG_PASS2) |
290 if (submit_stats(avc_context)) | |
291 return -1; | |
292 | |
4403 | 293 /* Now call into theora_encode_YUVin */ |
10553 | 294 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
|
295 if (result) { |
4403 | 296 const char* message; |
297 switch (result) { | |
10439 | 298 case -1: |
299 message = "differing frame sizes"; | |
300 break; | |
10553 | 301 case TH_EINVAL: |
10439 | 302 message = "encoder is not ready or is finished"; |
303 break; | |
304 default: | |
305 message = "unknown reason"; | |
306 break; | |
4403 | 307 } |
308 av_log(avc_context, AV_LOG_ERROR, "theora_encode_YUVin failed (%s) [%d]\n", message, result); | |
309 return -1; | |
310 } | |
311 | |
10554 | 312 if (avc_context->flags & CODEC_FLAG_PASS1) |
313 if (get_stats(avc_context, 0)) | |
314 return -1; | |
315 | |
4403 | 316 /* Pick up returned ogg_packet */ |
10553 | 317 result = th_encode_packetout(h->t_state, 0, &o_packet); |
4403 | 318 switch (result) { |
10439 | 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; | |
4403 | 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 | |
10680
d569841bd1b7
Clarify comment: although still hacky, it is correct for existing libtheora
conrad
parents:
10679
diff
changeset
|
337 // 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
|
338 // multithreaded (which will be disabled unless explictly requested) |
10439 | 339 avc_context->coded_frame->pts = frame->pts; |
10679 | 340 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
|
341 |
4403 | 342 return o_packet.bytes; |
343 } | |
344 | |
9007
043574c5c153
Add missing av_cold in static init/close functions.
stefano
parents:
8673
diff
changeset
|
345 static av_cold int encode_close(AVCodecContext* avc_context) |
4403 | 346 { |
347 TheoraContext *h = avc_context->priv_data; | |
348 | |
10553 | 349 th_encode_free(h->t_state); |
10554 | 350 av_freep(&h->stats); |
9951 | 351 av_freep(&avc_context->coded_frame); |
10554 | 352 av_freep(&avc_context->stats_out); |
9951 | 353 av_freep(&avc_context->extradata); |
354 avc_context->extradata_size = 0; | |
355 | |
10554 | 356 return 0; |
4403 | 357 } |
358 | |
11643
92236ee7be0f
cosmetics: Switch Doxygen comments to JavaDoc style.
diego
parents:
11560
diff
changeset
|
359 /** AVCodec struct exposed to libavcodec */ |
10439 | 360 AVCodec libtheora_encoder = { |
4403 | 361 .name = "libtheora", |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
10680
diff
changeset
|
362 .type = AVMEDIA_TYPE_VIDEO, |
4403 | 363 .id = CODEC_ID_THEORA, |
364 .priv_data_size = sizeof(TheoraContext), | |
365 .init = encode_init, | |
366 .close = encode_close, | |
367 .encode = encode_frame, | |
10554 | 368 .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
|
369 .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
|
370 .long_name = NULL_IF_CONFIG_SMALL("libtheora Theora"), |
4403 | 371 }; |