comparison libtheoraenc.c @ 10553:86c7e3c6de00 libavcodec

Update libtheora wrapper to use the 1.0 API
author conrad
date Sun, 22 Nov 2009 21:08:37 +0000
parents f1ef8d3221c8
children deabe9f7571b
comparison
equal deleted inserted replaced
10552:e2d17f7f9408 10553:86c7e3c6de00
34 #include "libavutil/intreadwrite.h" 34 #include "libavutil/intreadwrite.h"
35 #include "libavutil/log.h" 35 #include "libavutil/log.h"
36 #include "avcodec.h" 36 #include "avcodec.h"
37 37
38 /* libtheora includes */ 38 /* libtheora includes */
39 #include <theora/theora.h> 39 #include <theora/theoraenc.h>
40 40
41 typedef struct TheoraContext { 41 typedef struct TheoraContext {
42 theora_state t_state; 42 th_enc_ctx *t_state;
43 } TheoraContext; 43 } TheoraContext;
44 44
45 /*! 45 /*!
46 Concatenates an ogg_packet into the extradata. 46 Concatenates an ogg_packet into the extradata.
47 */ 47 */
78 return 0; 78 return 0;
79 } 79 }
80 80
81 static av_cold int encode_init(AVCodecContext* avc_context) 81 static av_cold int encode_init(AVCodecContext* avc_context)
82 { 82 {
83 theora_info t_info; 83 th_info t_info;
84 theora_comment t_comment; 84 th_comment t_comment;
85 ogg_packet o_packet; 85 ogg_packet o_packet;
86 unsigned int offset; 86 unsigned int offset;
87 TheoraContext *h = avc_context->priv_data; 87 TheoraContext *h = avc_context->priv_data;
88 uint32_t gop_size = avc_context->gop_size;
88 89
89 /* Set up the theora_info struct */ 90 /* Set up the theora_info struct */
90 theora_info_init(&t_info); 91 th_info_init(&t_info);
91 t_info.width = FFALIGN(avc_context->width, 16); 92 t_info.frame_width = FFALIGN(avc_context->width, 16);
92 t_info.height = FFALIGN(avc_context->height, 16); 93 t_info.frame_height = FFALIGN(avc_context->height, 16);
93 t_info.frame_width = avc_context->width; 94 t_info.pic_width = avc_context->width;
94 t_info.frame_height = avc_context->height; 95 t_info.pic_height = avc_context->height;
95 t_info.offset_x = 0; 96 t_info.pic_x = 0;
96 t_info.offset_y = avc_context->height & 0xf; 97 t_info.pic_y = 0;
97 /* Swap numerator and denominator as time_base in AVCodecContext gives the 98 /* Swap numerator and denominator as time_base in AVCodecContext gives the
98 * time period between frames, but theora_info needs the framerate. */ 99 * time period between frames, but theora_info needs the framerate. */
99 t_info.fps_numerator = avc_context->time_base.den; 100 t_info.fps_numerator = avc_context->time_base.den;
100 t_info.fps_denominator = avc_context->time_base.num; 101 t_info.fps_denominator = avc_context->time_base.num;
101 if (avc_context->sample_aspect_ratio.num) { 102 if (avc_context->sample_aspect_ratio.num) {
103 t_info.aspect_denominator = avc_context->sample_aspect_ratio.den; 104 t_info.aspect_denominator = avc_context->sample_aspect_ratio.den;
104 } else { 105 } else {
105 t_info.aspect_numerator = 1; 106 t_info.aspect_numerator = 1;
106 t_info.aspect_denominator = 1; 107 t_info.aspect_denominator = 1;
107 } 108 }
108 t_info.colorspace = OC_CS_UNSPECIFIED; 109 t_info.colorspace = TH_CS_UNSPECIFIED;
109 t_info.pixelformat = OC_PF_420; 110 t_info.pixel_fmt = TH_PF_420;
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
114 t_info.quick_p = 1;
115 t_info.dropframes_p = 0;
116 t_info.keyframe_auto_p = 1;
117 t_info.keyframe_data_target_bitrate = t_info.target_bitrate * 1.5;
118 t_info.keyframe_auto_threshold = 80;
119 t_info.noise_sensitivity = 1;
120 t_info.sharpness = 0;
121 111
122 if (avc_context->flags & CODEC_FLAG_QSCALE) { 112 if (avc_context->flags & CODEC_FLAG_QSCALE) {
123 /* to be constant with the libvorbis implementation, clip global_quality to 0 - 10 113 /* to be constant with the libvorbis implementation, clip global_quality to 0 - 10
124 Theora accepts a quality parameter p, which is: 114 Theora accepts a quality parameter p, which is:
125 * 0 <= p <=63 115 * 0 <= p <=63
131 t_info.target_bitrate = avc_context->bit_rate; 121 t_info.target_bitrate = avc_context->bit_rate;
132 t_info.quality = 0; 122 t_info.quality = 0;
133 } 123 }
134 124
135 /* Now initialise libtheora */ 125 /* Now initialise libtheora */
136 if (theora_encode_init(&(h->t_state), &t_info)) { 126 h->t_state = th_encode_alloc(&t_info);
127 if (!h->t_state) {
137 av_log(avc_context, AV_LOG_ERROR, "theora_encode_init failed\n"); 128 av_log(avc_context, AV_LOG_ERROR, "theora_encode_init failed\n");
138 return -1; 129 return -1;
139 } 130 }
140 131
141 /* Clear up theora_info struct */ 132 /* Clear up theora_info struct */
142 theora_info_clear(&t_info); 133 th_info_clear(&t_info);
134
135 if (th_encode_ctl(h->t_state, TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE,
136 &gop_size, sizeof(gop_size))) {
137 av_log(avc_context, AV_LOG_ERROR, "Error setting GOP size\n");
138 return -1;
139 }
143 140
144 /* 141 /*
145 Output first header packet consisting of theora 142 Output first header packet consisting of theora
146 header, comment, and tables. 143 header, comment, and tables.
147 144
148 Each one is prefixed with a 16bit size, then they 145 Each one is prefixed with a 16bit size, then they
149 are concatenated together into ffmpeg's extradata. 146 are concatenated together into ffmpeg's extradata.
150 */ 147 */
151 offset = 0; 148 offset = 0;
152 149
153 /* Header */ 150 /* Headers */
154 theora_encode_header(&(h->t_state), &o_packet); 151 th_comment_init(&t_comment);
155 if (concatenate_packet(&offset, avc_context, &o_packet)) 152
156 return -1; 153 while (th_encode_flushheader(h->t_state, &t_comment, &o_packet))
157 154 if (concatenate_packet(&offset, avc_context, &o_packet))
158 /* Comment */ 155 return -1;
159 theora_comment_init(&t_comment); 156
160 theora_encode_comment(&t_comment, &o_packet); 157 th_comment_clear(&t_comment);
161 if (concatenate_packet(&offset, avc_context, &o_packet))
162 return -1;
163 /* Clear up theora_comment struct before we reset the packet */
164 theora_comment_clear(&t_comment);
165 /* And despite documentation to the contrary, theora_comment_clear
166 * does not release the packet */
167 ogg_packet_clear(&o_packet);
168
169 /* Tables */
170 theora_encode_tables(&(h->t_state), &o_packet);
171 if (concatenate_packet(&offset, avc_context, &o_packet))
172 return -1;
173 158
174 /* Set up the output AVFrame */ 159 /* Set up the output AVFrame */
175 avc_context->coded_frame= avcodec_alloc_frame(); 160 avc_context->coded_frame= avcodec_alloc_frame();
176 161
177 return 0; 162 return 0;
178 } 163 }
179 164
180 static int encode_frame(AVCodecContext* avc_context, uint8_t *outbuf, 165 static int encode_frame(AVCodecContext* avc_context, uint8_t *outbuf,
181 int buf_size, void *data) 166 int buf_size, void *data)
182 { 167 {
183 yuv_buffer t_yuv_buffer; 168 th_ycbcr_buffer t_yuv_buffer;
184 TheoraContext *h = avc_context->priv_data; 169 TheoraContext *h = avc_context->priv_data;
185 AVFrame *frame = data; 170 AVFrame *frame = data;
186 ogg_packet o_packet; 171 ogg_packet o_packet;
187 int result; 172 int result, i;
188 173
189 assert(avc_context->pix_fmt == PIX_FMT_YUV420P); 174 assert(avc_context->pix_fmt == PIX_FMT_YUV420P);
190 175
191 /* Copy planes to the theora yuv_buffer */ 176 /* Copy planes to the theora yuv_buffer */
192 if (frame->linesize[1] != frame->linesize[2]) { 177 for (i = 0; i < 3; i++) {
193 av_log(avc_context, AV_LOG_ERROR, "U and V stride differ\n"); 178 t_yuv_buffer[i].width = FFALIGN(avc_context->width, 16) >> !!i;
194 return -1; 179 t_yuv_buffer[i].height = FFALIGN(avc_context->height, 16) >> !!i;
195 } 180 t_yuv_buffer[i].stride = frame->linesize[i];
196 181 t_yuv_buffer[i].data = frame->data[i];
197 t_yuv_buffer.y_width = FFALIGN(avc_context->width, 16); 182 }
198 t_yuv_buffer.y_height = FFALIGN(avc_context->height, 16);
199 t_yuv_buffer.y_stride = frame->linesize[0];
200 t_yuv_buffer.uv_width = t_yuv_buffer.y_width / 2;
201 t_yuv_buffer.uv_height = t_yuv_buffer.y_height / 2;
202 t_yuv_buffer.uv_stride = frame->linesize[1];
203
204 t_yuv_buffer.y = frame->data[0];
205 t_yuv_buffer.u = frame->data[1];
206 t_yuv_buffer.v = frame->data[2];
207 183
208 /* Now call into theora_encode_YUVin */ 184 /* Now call into theora_encode_YUVin */
209 result = theora_encode_YUVin(&(h->t_state), &t_yuv_buffer); 185 result = th_encode_ycbcr_in(h->t_state, t_yuv_buffer);
210 if (result) { 186 if (result) {
211 const char* message; 187 const char* message;
212 switch (result) { 188 switch (result) {
213 case -1: 189 case -1:
214 message = "differing frame sizes"; 190 message = "differing frame sizes";
215 break; 191 break;
216 case OC_EINVAL: 192 case TH_EINVAL:
217 message = "encoder is not ready or is finished"; 193 message = "encoder is not ready or is finished";
218 break; 194 break;
219 default: 195 default:
220 message = "unknown reason"; 196 message = "unknown reason";
221 break; 197 break;
223 av_log(avc_context, AV_LOG_ERROR, "theora_encode_YUVin failed (%s) [%d]\n", message, result); 199 av_log(avc_context, AV_LOG_ERROR, "theora_encode_YUVin failed (%s) [%d]\n", message, result);
224 return -1; 200 return -1;
225 } 201 }
226 202
227 /* Pick up returned ogg_packet */ 203 /* Pick up returned ogg_packet */
228 result = theora_encode_packetout(&(h->t_state), 0, &o_packet); 204 result = th_encode_packetout(h->t_state, 0, &o_packet);
229 switch (result) { 205 switch (result) {
230 case 0: 206 case 0:
231 /* No packet is ready */ 207 /* No packet is ready */
232 return 0; 208 return 0;
233 case 1: 209 case 1:
256 ogg_packet o_packet; 232 ogg_packet o_packet;
257 TheoraContext *h = avc_context->priv_data; 233 TheoraContext *h = avc_context->priv_data;
258 int result; 234 int result;
259 const char* message; 235 const char* message;
260 236
261 result = theora_encode_packetout(&(h->t_state), 1, &o_packet); 237 result = th_encode_packetout(h->t_state, 1, &o_packet);
262 theora_clear(&(h->t_state)); 238 th_encode_free(h->t_state);
263 av_freep(&avc_context->coded_frame); 239 av_freep(&avc_context->coded_frame);
264 av_freep(&avc_context->extradata); 240 av_freep(&avc_context->extradata);
265 avc_context->extradata_size = 0; 241 avc_context->extradata_size = 0;
266 242
267 switch (result) { 243 switch (result) {