Mercurial > libavcodec.hg
annotate libtheoraenc.c @ 10381:9262948fd649 libavcodec
Hack: set the coded frame PTS to the incoming PTS.
This is not correct, but libtheora does not seem to provide a way
to get the correct value, and this is necessary to make encoding
produce sensible time stamps when encoded content is variable
FPS or the time base is simply different from FPS.
Somewhat fixes issue 1197.
author | reimar |
---|---|
date | Sat, 10 Oct 2009 14:43:31 +0000 |
parents | dfb91c11fe9c |
children | 00bd0c4c1489 |
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" |
4403 | 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 { | |
9952
4b3abcad0628
Fix "warning: assignment discards qualifiers from pointer target type"
conrad
parents:
9951
diff
changeset
|
50 const char* message = NULL; |
4403 | 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; | |
5089 | 73 AV_WB16(avc_context->extradata + (*offset), packet->bytes); |
74 *offset += 2; | |
4403 | 75 memcpy( avc_context->extradata + (*offset), packet->packet, packet->bytes ); |
76 (*offset) += packet->bytes; | |
77 return 0; | |
78 } | |
79 | |
9007
043574c5c153
Add missing av_cold in static init/close functions.
stefano
parents:
8673
diff
changeset
|
80 static av_cold int encode_init(AVCodecContext* avc_context) |
4403 | 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 ); | |
9687 | 90 t_info.width = FFALIGN(avc_context->width, 16); |
91 t_info.height = FFALIGN(avc_context->height, 16); | |
4403 | 92 t_info.frame_width = avc_context->width; |
93 t_info.frame_height = avc_context->height; | |
94 t_info.offset_x = 0; | |
9687 | 95 t_info.offset_y = avc_context->height & 0xf; |
4496
a02a0d06e99b
Add a comment about swapped numerator and denominator.
diego
parents:
4403
diff
changeset
|
96 /* 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
|
97 * time period between frames, but theora_info needs the framerate. */ |
4403 | 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.keyframe_frequency = avc_context->gop_size; | |
110 t_info.keyframe_frequency_force = avc_context->gop_size; | |
111 t_info.keyframe_mindistance = avc_context->keyint_min; | |
112 | |
113 t_info.quick_p = 1; | |
114 t_info.dropframes_p = 0; | |
115 t_info.keyframe_auto_p = 1; | |
116 t_info.keyframe_data_target_bitrate = t_info.target_bitrate * 1.5; | |
117 t_info.keyframe_auto_threshold = 80; | |
118 t_info.noise_sensitivity = 1; | |
119 t_info.sharpness = 0; | |
120 | |
10332 | 121 if (avc_context->flags & CODEC_FLAG_QSCALE) { |
122 /* to be constant with the libvorbis implementation, clip global_quality to 0 - 10 | |
123 Theora accepts a quality parameter p, which is: | |
124 * 0 <= p <=63 | |
125 * an int value | |
126 */ | |
127 t_info.quality = av_clip(avc_context->global_quality / (float)FF_QP2LAMBDA, 0, 10) * 6.3; | |
128 t_info.target_bitrate = 0; | |
129 } else { | |
130 t_info.target_bitrate = avc_context->bit_rate; | |
131 t_info.quality = 0; | |
132 } | |
133 | |
4403 | 134 /* Now initialise libtheora */ |
135 if (theora_encode_init( &(h->t_state), &t_info ) != 0) { | |
136 av_log(avc_context, AV_LOG_ERROR, "theora_encode_init failed\n"); | |
137 return -1; | |
138 } | |
139 | |
140 /* Clear up theora_info struct */ | |
141 theora_info_clear( &t_info ); | |
142 | |
143 /* | |
144 Output first header packet consisting of theora | |
145 header, comment, and tables. | |
146 | |
147 Each one is prefixed with a 16bit size, then they | |
148 are concatenated together into ffmpeg's extradata. | |
149 */ | |
150 offset = 0; | |
151 | |
152 /* Header */ | |
153 theora_encode_header( &(h->t_state), &o_packet ); | |
154 if (concatenate_packet( &offset, avc_context, &o_packet ) != 0) { | |
155 return -1; | |
156 } | |
157 | |
158 /* Comment */ | |
159 theora_comment_init( &t_comment ); | |
160 theora_encode_comment( &t_comment, &o_packet ); | |
161 if (concatenate_packet( &offset, avc_context, &o_packet ) != 0) { | |
162 return -1; | |
163 } | |
9951 | 164 /* Clear up theora_comment struct before we reset the packet */ |
165 theora_comment_clear( &t_comment ); | |
166 /* And despite documentation to the contrary, theora_comment_clear | |
167 * does not release the packet */ | |
168 ogg_packet_clear(&o_packet); | |
4403 | 169 |
170 /* Tables */ | |
171 theora_encode_tables( &(h->t_state), &o_packet ); | |
172 if (concatenate_packet( &offset, avc_context, &o_packet ) != 0) { | |
173 return -1; | |
174 } | |
175 | |
176 /* Set up the output AVFrame */ | |
177 avc_context->coded_frame= avcodec_alloc_frame(); | |
178 | |
179 return 0; | |
180 } | |
181 | |
182 static int encode_frame( | |
183 AVCodecContext* avc_context, | |
184 uint8_t *outbuf, | |
185 int buf_size, | |
186 void *data) | |
187 { | |
188 yuv_buffer t_yuv_buffer; | |
189 TheoraContext *h = avc_context->priv_data; | |
190 AVFrame *frame = data; | |
191 ogg_packet o_packet; | |
192 int result; | |
193 | |
194 assert(avc_context->pix_fmt == PIX_FMT_YUV420P); | |
195 | |
196 /* Copy planes to the theora yuv_buffer */ | |
197 if (frame->linesize[1] != frame->linesize[2]) { | |
198 av_log(avc_context, AV_LOG_ERROR, "U and V stride differ\n"); | |
199 return -1; | |
200 } | |
201 | |
9687 | 202 t_yuv_buffer.y_width = FFALIGN(avc_context->width, 16); |
203 t_yuv_buffer.y_height = FFALIGN(avc_context->height, 16); | |
4403 | 204 t_yuv_buffer.y_stride = frame->linesize[0]; |
205 t_yuv_buffer.uv_width = t_yuv_buffer.y_width / 2; | |
206 t_yuv_buffer.uv_height = t_yuv_buffer.y_height / 2; | |
207 t_yuv_buffer.uv_stride = frame->linesize[1]; | |
208 | |
209 t_yuv_buffer.y = frame->data[0]; | |
210 t_yuv_buffer.u = frame->data[1]; | |
211 t_yuv_buffer.v = frame->data[2]; | |
212 | |
213 /* Now call into theora_encode_YUVin */ | |
214 result = theora_encode_YUVin( &(h->t_state), &t_yuv_buffer ); | |
215 if (result != 0) { | |
216 const char* message; | |
217 switch (result) { | |
218 case -1: | |
219 message = "differing frame sizes"; | |
220 break; | |
221 case OC_EINVAL: | |
222 message = "encoder is not ready or is finished"; | |
223 break; | |
224 default: | |
225 message = "unknown reason"; | |
226 break; | |
227 } | |
228 av_log(avc_context, AV_LOG_ERROR, "theora_encode_YUVin failed (%s) [%d]\n", message, result); | |
229 return -1; | |
230 } | |
231 | |
232 /* Pick up returned ogg_packet */ | |
233 result = theora_encode_packetout( &(h->t_state), 0, &o_packet ); | |
234 switch (result) { | |
235 case 0: | |
236 /* No packet is ready */ | |
237 return 0; | |
238 case 1: | |
239 /* Success, we have a packet */ | |
240 break; | |
241 default: | |
242 av_log(avc_context, AV_LOG_ERROR, "theora_encode_packetout failed [%d]\n", result); | |
243 return -1; | |
244 } | |
245 | |
246 /* Copy ogg_packet content out to buffer */ | |
247 if (buf_size < o_packet.bytes) { | |
248 av_log(avc_context, AV_LOG_ERROR, "encoded frame too large\n"); | |
249 return -1; | |
250 } | |
251 memcpy(outbuf, o_packet.packet, o_packet.bytes); | |
252 | |
10381
9262948fd649
Hack: set the coded frame PTS to the incoming PTS.
reimar
parents:
10332
diff
changeset
|
253 // HACK: does not take codec delay into account (neither does the decoder though) |
9262948fd649
Hack: set the coded frame PTS to the incoming PTS.
reimar
parents:
10332
diff
changeset
|
254 avc_context->coded_frame->pts= frame->pts; |
9262948fd649
Hack: set the coded frame PTS to the incoming PTS.
reimar
parents:
10332
diff
changeset
|
255 |
4403 | 256 return o_packet.bytes; |
257 } | |
258 | |
9007
043574c5c153
Add missing av_cold in static init/close functions.
stefano
parents:
8673
diff
changeset
|
259 static av_cold int encode_close(AVCodecContext* avc_context) |
4403 | 260 { |
261 ogg_packet o_packet; | |
262 TheoraContext *h = avc_context->priv_data; | |
263 int result; | |
264 const char* message; | |
265 | |
266 result = theora_encode_packetout( &(h->t_state), 1, &o_packet ); | |
267 theora_clear( &(h->t_state) ); | |
9951 | 268 av_freep(&avc_context->coded_frame); |
269 av_freep(&avc_context->extradata); | |
270 avc_context->extradata_size = 0; | |
271 | |
4403 | 272 switch (result) { |
273 case 0:/* No packet is ready */ | |
274 case -1:/* Encoding finished */ | |
275 return 0; | |
276 case 1: | |
277 /* We have a packet */ | |
278 message = "gave us a packet"; | |
279 break; | |
280 default: | |
281 message = "unknown reason"; | |
282 break; | |
283 } | |
284 av_log(avc_context, AV_LOG_ERROR, "theora_encode_packetout failed (%s) [%d]\n", message, result); | |
285 return -1; | |
286 } | |
287 | |
6788 | 288 static const enum PixelFormat supported_pixel_formats[] = { PIX_FMT_YUV420P, PIX_FMT_NONE }; |
4403 | 289 |
290 /*! AVCodec struct exposed to libavcodec */ | |
291 AVCodec libtheora_encoder = | |
292 { | |
293 .name = "libtheora", | |
294 .type = CODEC_TYPE_VIDEO, | |
295 .id = CODEC_ID_THEORA, | |
296 .priv_data_size = sizeof(TheoraContext), | |
297 .init = encode_init, | |
298 .close = encode_close, | |
299 .encode = encode_frame, | |
300 .pix_fmts = supported_pixel_formats, | |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6788
diff
changeset
|
301 .long_name = NULL_IF_CONFIG_SMALL("libtheora Theora"), |
4403 | 302 }; |