Mercurial > libavcodec.hg
annotate libvpxenc.c @ 12266:48d6738904a9 libavcodec
Fix SPLATB_REG mess. Used to be a if/elseif/elseif/elseif spaghetti, so this
splits it into small optimization-specific macros which are selected for each
DSP function. The advantage of this approach is that the sse4 functions now
use the ssse3 codepath also without needing an explicit sse4 codepath.
author | rbultje |
---|---|
date | Sat, 24 Jul 2010 19:33:05 +0000 |
parents | 36940062c081 |
children | bb7b7602b40e |
rev | line source |
---|---|
11821 | 1 /* |
2 * Copyright (c) 2010, Google, Inc. | |
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 * VP8 encoder support via libvpx | |
24 */ | |
25 | |
26 #define VPX_DISABLE_CTRL_TYPECHECKS 1 | |
27 #define VPX_CODEC_DISABLE_COMPAT 1 | |
28 #include <vpx/vpx_encoder.h> | |
29 #include <vpx/vp8cx.h> | |
30 | |
31 #include "avcodec.h" | |
32 #include "libavutil/base64.h" | |
33 | |
34 /** | |
35 * Portion of struct vpx_codec_cx_pkt from vpx_encoder.h. | |
36 * One encoded frame returned from the library. | |
37 */ | |
38 struct FrameListData { | |
39 void *buf; /**≤ compressed data buffer */ | |
40 size_t sz; /**≤ length of compressed data */ | |
41 int64_t pts; /**≤ time stamp to show frame | |
42 (in timebase units) */ | |
43 unsigned long duration; /**≤ duration to show frame | |
44 (in timebase units) */ | |
45 uint32_t flags; /**≤ flags for this frame */ | |
46 struct FrameListData *next; | |
47 }; | |
48 | |
49 typedef struct VP8EncoderContext { | |
50 struct vpx_codec_ctx encoder; | |
51 struct vpx_image rawimg; | |
52 struct vpx_fixed_buf twopass_stats; | |
53 unsigned long deadline; //i.e., RT/GOOD/BEST | |
54 struct FrameListData *coded_frame_list; | |
55 } VP8Context; | |
56 | |
57 /** String mappings for enum vp8e_enc_control_id */ | |
58 static const char *ctlidstr[] = { | |
59 [VP8E_UPD_ENTROPY] = "VP8E_UPD_ENTROPY", | |
60 [VP8E_UPD_REFERENCE] = "VP8E_UPD_REFERENCE", | |
61 [VP8E_USE_REFERENCE] = "VP8E_USE_REFERENCE", | |
62 [VP8E_SET_ROI_MAP] = "VP8E_SET_ROI_MAP", | |
63 [VP8E_SET_ACTIVEMAP] = "VP8E_SET_ACTIVEMAP", | |
64 [VP8E_SET_SCALEMODE] = "VP8E_SET_SCALEMODE", | |
65 [VP8E_SET_CPUUSED] = "VP8E_SET_CPUUSED", | |
66 [VP8E_SET_ENABLEAUTOALTREF] = "VP8E_SET_ENABLEAUTOALTREF", | |
67 [VP8E_SET_NOISE_SENSITIVITY] = "VP8E_SET_NOISE_SENSITIVITY", | |
68 [VP8E_SET_SHARPNESS] = "VP8E_SET_SHARPNESS", | |
69 [VP8E_SET_STATIC_THRESHOLD] = "VP8E_SET_STATIC_THRESHOLD", | |
70 [VP8E_SET_TOKEN_PARTITIONS] = "VP8E_SET_TOKEN_PARTITIONS", | |
71 [VP8E_GET_LAST_QUANTIZER] = "VP8E_GET_LAST_QUANTIZER", | |
72 [VP8E_SET_ARNR_MAXFRAMES] = "VP8E_SET_ARNR_MAXFRAMES", | |
73 [VP8E_SET_ARNR_STRENGTH] = "VP8E_SET_ARNR_STRENGTH", | |
74 [VP8E_SET_ARNR_TYPE] = "VP8E_SET_ARNR_TYPE", | |
75 }; | |
76 | |
77 static av_cold void log_encoder_error(AVCodecContext *avctx, const char *desc) | |
78 { | |
79 VP8Context *ctx = avctx->priv_data; | |
80 const char *error = vpx_codec_error(&ctx->encoder); | |
81 const char *detail = vpx_codec_error_detail(&ctx->encoder); | |
82 | |
83 av_log(avctx, AV_LOG_ERROR, "%s: %s\n", desc, error); | |
84 if (detail) | |
85 av_log(avctx, AV_LOG_ERROR, " Additional information: %s\n", detail); | |
86 } | |
87 | |
88 static av_cold void dump_enc_cfg(AVCodecContext *avctx, | |
89 const struct vpx_codec_enc_cfg *cfg) | |
90 { | |
91 int width = -30; | |
92 int level = AV_LOG_DEBUG; | |
93 | |
94 av_log(avctx, level, "vpx_codec_enc_cfg\n"); | |
95 av_log(avctx, level, "generic settings\n" | |
96 " %*s%u\n %*s%u\n %*s%u\n %*s%u\n %*s%u\n" | |
97 " %*s{%u/%u}\n %*s%u\n %*s%d\n %*s%u\n", | |
98 width, "g_usage:", cfg->g_usage, | |
99 width, "g_threads:", cfg->g_threads, | |
100 width, "g_profile:", cfg->g_profile, | |
101 width, "g_w:", cfg->g_w, | |
102 width, "g_h:", cfg->g_h, | |
103 width, "g_timebase:", cfg->g_timebase.num, cfg->g_timebase.den, | |
104 width, "g_error_resilient:", cfg->g_error_resilient, | |
105 width, "g_pass:", cfg->g_pass, | |
106 width, "g_lag_in_frames:", cfg->g_lag_in_frames); | |
107 av_log(avctx, level, "rate control settings\n" | |
108 " %*s%u\n %*s%u\n %*s%u\n %*s%u\n" | |
109 " %*s%d\n %*s%p(%zu)\n %*s%u\n", | |
110 width, "rc_dropframe_thresh:", cfg->rc_dropframe_thresh, | |
111 width, "rc_resize_allowed:", cfg->rc_resize_allowed, | |
112 width, "rc_resize_up_thresh:", cfg->rc_resize_up_thresh, | |
113 width, "rc_resize_down_thresh:", cfg->rc_resize_down_thresh, | |
114 width, "rc_end_usage:", cfg->rc_end_usage, | |
115 width, "rc_twopass_stats_in:", cfg->rc_twopass_stats_in.buf, cfg->rc_twopass_stats_in.sz, | |
116 width, "rc_target_bitrate:", cfg->rc_target_bitrate); | |
117 av_log(avctx, level, "quantizer settings\n" | |
118 " %*s%u\n %*s%u\n", | |
119 width, "rc_min_quantizer:", cfg->rc_min_quantizer, | |
120 width, "rc_max_quantizer:", cfg->rc_max_quantizer); | |
121 av_log(avctx, level, "bitrate tolerance\n" | |
122 " %*s%u\n %*s%u\n", | |
123 width, "rc_undershoot_pct:", cfg->rc_undershoot_pct, | |
124 width, "rc_overshoot_pct:", cfg->rc_overshoot_pct); | |
125 av_log(avctx, level, "decoder buffer model\n" | |
126 " %*s%u\n %*s%u\n %*s%u\n", | |
127 width, "rc_buf_sz:", cfg->rc_buf_sz, | |
128 width, "rc_buf_initial_sz:", cfg->rc_buf_initial_sz, | |
129 width, "rc_buf_optimal_sz:", cfg->rc_buf_optimal_sz); | |
130 av_log(avctx, level, "2 pass rate control settings\n" | |
131 " %*s%u\n %*s%u\n %*s%u\n", | |
132 width, "rc_2pass_vbr_bias_pct:", cfg->rc_2pass_vbr_bias_pct, | |
133 width, "rc_2pass_vbr_minsection_pct:", cfg->rc_2pass_vbr_minsection_pct, | |
134 width, "rc_2pass_vbr_maxsection_pct:", cfg->rc_2pass_vbr_maxsection_pct); | |
135 av_log(avctx, level, "keyframing settings\n" | |
136 " %*s%d\n %*s%u\n %*s%u\n", | |
137 width, "kf_mode:", cfg->kf_mode, | |
138 width, "kf_min_dist:", cfg->kf_min_dist, | |
139 width, "kf_max_dist:", cfg->kf_max_dist); | |
140 av_log(avctx, level, "\n"); | |
141 } | |
142 | |
143 static void coded_frame_add(void *list, struct FrameListData *cx_frame) | |
144 { | |
145 struct FrameListData **p = list; | |
146 | |
147 while (*p != NULL) | |
148 p = &(*p)->next; | |
149 *p = cx_frame; | |
150 cx_frame->next = NULL; | |
151 } | |
152 | |
153 static av_cold void free_coded_frame(struct FrameListData *cx_frame) | |
154 { | |
155 av_freep(&cx_frame->buf); | |
156 av_freep(&cx_frame); | |
157 } | |
158 | |
159 static av_cold void free_frame_list(struct FrameListData *list) | |
160 { | |
161 struct FrameListData *p = list; | |
162 | |
163 while (p) { | |
164 list = list->next; | |
165 free_coded_frame(p); | |
166 p = list; | |
167 } | |
168 } | |
169 | |
170 static av_cold int codecctl_int(AVCodecContext *avctx, | |
171 enum vp8e_enc_control_id id, int val) | |
172 { | |
173 VP8Context *ctx = avctx->priv_data; | |
174 char buf[80]; | |
175 int width = -30; | |
176 int res; | |
177 | |
178 snprintf(buf, sizeof(buf), "%s:", ctlidstr[id]); | |
179 av_log(avctx, AV_LOG_DEBUG, " %*s%d\n", width, buf, val); | |
180 | |
181 res = vpx_codec_control(&ctx->encoder, id, val); | |
182 if (res != VPX_CODEC_OK) { | |
183 snprintf(buf, sizeof(buf), "Failed to set %s codec control", | |
184 ctlidstr[id]); | |
185 log_encoder_error(avctx, buf); | |
186 } | |
187 | |
188 return res == VPX_CODEC_OK ? 0 : AVERROR(EINVAL); | |
189 } | |
190 | |
191 static av_cold int vp8_free(AVCodecContext *avctx) | |
192 { | |
193 VP8Context *ctx = avctx->priv_data; | |
194 | |
195 vpx_codec_destroy(&ctx->encoder); | |
196 av_freep(&ctx->twopass_stats.buf); | |
197 av_freep(&avctx->coded_frame); | |
198 av_freep(&avctx->stats_out); | |
199 free_frame_list(ctx->coded_frame_list); | |
200 return 0; | |
201 } | |
202 | |
203 static av_cold int vp8_init(AVCodecContext *avctx) | |
204 { | |
205 VP8Context *ctx = avctx->priv_data; | |
206 const struct vpx_codec_iface *iface = &vpx_codec_vp8_cx_algo; | |
207 int cpuused = 3; | |
208 struct vpx_codec_enc_cfg enccfg; | |
209 int res; | |
210 | |
211 av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str()); | |
212 av_log(avctx, AV_LOG_VERBOSE, "%s\n", vpx_codec_build_config()); | |
213 | |
214 if ((res = vpx_codec_enc_config_default(iface, &enccfg, 0)) != VPX_CODEC_OK) { | |
215 av_log(avctx, AV_LOG_ERROR, "Failed to get config: %s\n", | |
216 vpx_codec_err_to_string(res)); | |
217 return AVERROR(EINVAL); | |
218 } | |
219 dump_enc_cfg(avctx, &enccfg); | |
220 | |
221 enccfg.g_w = avctx->width; | |
222 enccfg.g_h = avctx->height; | |
223 enccfg.g_timebase.num = avctx->time_base.num; | |
224 enccfg.g_timebase.den = avctx->time_base.den; | |
225 enccfg.g_threads = avctx->thread_count; | |
226 | |
227 if (avctx->flags & CODEC_FLAG_PASS1) | |
228 enccfg.g_pass = VPX_RC_FIRST_PASS; | |
229 else if (avctx->flags & CODEC_FLAG_PASS2) | |
230 enccfg.g_pass = VPX_RC_LAST_PASS; | |
231 else | |
232 enccfg.g_pass = VPX_RC_ONE_PASS; | |
233 | |
234 if (avctx->rc_min_rate == avctx->rc_max_rate && | |
235 avctx->rc_min_rate == avctx->bit_rate) | |
236 enccfg.rc_end_usage = VPX_CBR; | |
237 enccfg.rc_target_bitrate = av_rescale_rnd(avctx->bit_rate, 1, 1000, | |
238 AV_ROUND_NEAR_INF); | |
239 | |
12152
d102b12f69dc
Do not map video quantizer scale (from 1-51 to 0-63) for libvpx anymore.
cehoyos
parents:
12140
diff
changeset
|
240 enccfg.rc_min_quantizer = avctx->qmin; |
d102b12f69dc
Do not map video quantizer scale (from 1-51 to 0-63) for libvpx anymore.
cehoyos
parents:
12140
diff
changeset
|
241 enccfg.rc_max_quantizer = avctx->qmax; |
11852
24a6c651c3f3
libvpx: Set the libvpx frame dropping threshold to frame_skip_threshold
mstorsjo
parents:
11851
diff
changeset
|
242 enccfg.rc_dropframe_thresh = avctx->frame_skip_threshold; |
11821 | 243 |
12226 | 244 //0-100 (0 => CBR, 100 => VBR) |
245 enccfg.rc_2pass_vbr_bias_pct = round(avctx->qcompress * 100); | |
246 enccfg.rc_2pass_vbr_minsection_pct = | |
247 avctx->rc_min_rate * 100 / avctx->bit_rate; | |
248 if (avctx->rc_max_rate) | |
249 enccfg.rc_2pass_vbr_maxsection_pct = | |
250 avctx->rc_max_rate * 100 / avctx->bit_rate; | |
251 | |
11851 | 252 //_enc_init() will balk if kf_min_dist differs from max w/VPX_KF_AUTO |
11821 | 253 if (avctx->keyint_min == avctx->gop_size) |
254 enccfg.kf_min_dist = avctx->keyint_min; | |
255 enccfg.kf_max_dist = avctx->gop_size; | |
256 | |
257 if (enccfg.g_pass == VPX_RC_FIRST_PASS) | |
258 enccfg.g_lag_in_frames = 0; | |
259 else if (enccfg.g_pass == VPX_RC_LAST_PASS) { | |
260 int decode_size; | |
261 | |
262 if (!avctx->stats_in) { | |
263 av_log(avctx, AV_LOG_ERROR, "No stats file for second pass\n"); | |
264 return AVERROR_INVALIDDATA; | |
265 } | |
266 | |
267 ctx->twopass_stats.sz = strlen(avctx->stats_in) * 3 / 4; | |
268 ctx->twopass_stats.buf = av_malloc(ctx->twopass_stats.sz); | |
269 if (!ctx->twopass_stats.buf) { | |
270 av_log(avctx, AV_LOG_ERROR, | |
271 "Stat buffer alloc (%zu bytes) failed\n", | |
272 ctx->twopass_stats.sz); | |
273 return AVERROR(ENOMEM); | |
274 } | |
275 decode_size = av_base64_decode(ctx->twopass_stats.buf, avctx->stats_in, | |
276 ctx->twopass_stats.sz); | |
277 if (decode_size < 0) { | |
278 av_log(avctx, AV_LOG_ERROR, "Stat buffer decode failed\n"); | |
279 return AVERROR_INVALIDDATA; | |
280 } | |
281 | |
282 ctx->twopass_stats.sz = decode_size; | |
283 enccfg.rc_twopass_stats_in = ctx->twopass_stats; | |
284 } | |
285 | |
286 ctx->deadline = VPX_DL_GOOD_QUALITY; | |
12140
3d186eff2224
Set libvpx encoding profile to libavcodec's profile.
cehoyos
parents:
11852
diff
changeset
|
287 /* 0-3: For non-zero values the encoder increasingly optimizes for reduced |
3d186eff2224
Set libvpx encoding profile to libavcodec's profile.
cehoyos
parents:
11852
diff
changeset
|
288 complexity playback on low powered devices at the expense of encode |
3d186eff2224
Set libvpx encoding profile to libavcodec's profile.
cehoyos
parents:
11852
diff
changeset
|
289 quality. */ |
3d186eff2224
Set libvpx encoding profile to libavcodec's profile.
cehoyos
parents:
11852
diff
changeset
|
290 if (avctx->profile != FF_PROFILE_UNKNOWN) |
3d186eff2224
Set libvpx encoding profile to libavcodec's profile.
cehoyos
parents:
11852
diff
changeset
|
291 enccfg.g_profile = avctx->profile; |
11821 | 292 |
293 dump_enc_cfg(avctx, &enccfg); | |
294 /* Construct Encoder Context */ | |
295 res = vpx_codec_enc_init(&ctx->encoder, iface, &enccfg, 0); | |
296 if (res != VPX_CODEC_OK) { | |
297 log_encoder_error(avctx, "Failed to initialize encoder"); | |
298 return AVERROR(EINVAL); | |
299 } | |
300 | |
301 //codec control failures are currently treated only as warnings | |
302 av_log(avctx, AV_LOG_DEBUG, "vpx_codec_control\n"); | |
303 codecctl_int(avctx, VP8E_SET_CPUUSED, cpuused); | |
304 codecctl_int(avctx, VP8E_SET_NOISE_SENSITIVITY, avctx->noise_reduction); | |
305 | |
306 //provide dummy value to initialize wrapper, values will be updated each _encode() | |
307 vpx_img_wrap(&ctx->rawimg, VPX_IMG_FMT_I420, avctx->width, avctx->height, 1, | |
308 (unsigned char*)1); | |
309 | |
310 avctx->coded_frame = avcodec_alloc_frame(); | |
311 if (!avctx->coded_frame) { | |
312 av_log(avctx, AV_LOG_ERROR, "Error allocating coded frame\n"); | |
313 vp8_free(avctx); | |
314 return AVERROR(ENOMEM); | |
315 } | |
316 return 0; | |
317 } | |
318 | |
319 static inline void cx_pktcpy(struct FrameListData *dst, | |
320 const struct vpx_codec_cx_pkt *src) | |
321 { | |
322 dst->pts = src->data.frame.pts; | |
323 dst->duration = src->data.frame.duration; | |
324 dst->flags = src->data.frame.flags; | |
325 dst->sz = src->data.frame.sz; | |
326 dst->buf = src->data.frame.buf; | |
327 } | |
328 | |
329 /** | |
330 * Store coded frame information in format suitable for return from encode(). | |
331 * | |
332 * Write buffer information from @a cx_frame to @a buf & @a buf_size. | |
333 * Timing/frame details to @a coded_frame. | |
334 * @return Frame size written to @a buf on success | |
335 * @return AVERROR(EINVAL) on error | |
336 */ | |
337 static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, | |
338 uint8_t *buf, int buf_size, AVFrame *coded_frame) | |
339 { | |
340 if ((int) cx_frame->sz <= buf_size) { | |
341 buf_size = cx_frame->sz; | |
342 memcpy(buf, cx_frame->buf, buf_size); | |
343 coded_frame->pts = cx_frame->pts; | |
344 coded_frame->key_frame = !!(cx_frame->flags & VPX_FRAME_IS_KEY); | |
345 | |
346 if (coded_frame->key_frame) | |
347 coded_frame->pict_type = FF_I_TYPE; | |
348 else | |
349 coded_frame->pict_type = FF_P_TYPE; | |
350 } else { | |
351 av_log(avctx, AV_LOG_ERROR, | |
352 "Compressed frame larger than storage provided! (%zu/%d)\n", | |
353 cx_frame->sz, buf_size); | |
354 return AVERROR(EINVAL); | |
355 } | |
356 return buf_size; | |
357 } | |
358 | |
359 /** | |
360 * Queue multiple output frames from the encoder, returning the front-most. | |
361 * In cases where vpx_codec_get_cx_data() returns more than 1 frame append | |
362 * the frame queue. Return the head frame if available. | |
363 * @return Stored frame size | |
364 * @return AVERROR(EINVAL) on output size error | |
365 * @return AVERROR(ENOMEM) on coded frame queue data allocation error | |
366 */ | |
367 static int queue_frames(AVCodecContext *avctx, uint8_t *buf, int buf_size, | |
368 AVFrame *coded_frame) | |
369 { | |
370 VP8Context *ctx = avctx->priv_data; | |
371 const struct vpx_codec_cx_pkt *pkt; | |
372 const void *iter = NULL; | |
373 int size = 0; | |
374 | |
375 if (ctx->coded_frame_list) { | |
376 struct FrameListData *cx_frame = ctx->coded_frame_list; | |
377 /* return the leading frame if we've already begun queueing */ | |
378 size = storeframe(avctx, cx_frame, buf, buf_size, coded_frame); | |
379 if (size < 0) | |
380 return AVERROR(EINVAL); | |
381 ctx->coded_frame_list = cx_frame->next; | |
382 free_coded_frame(cx_frame); | |
383 } | |
384 | |
385 /* consume all available output from the encoder before returning. buffers | |
386 are only good through the next vpx_codec call */ | |
387 while ((pkt = vpx_codec_get_cx_data(&ctx->encoder, &iter))) { | |
388 switch (pkt->kind) { | |
389 case VPX_CODEC_CX_FRAME_PKT: | |
390 if (!size) { | |
391 struct FrameListData cx_frame; | |
392 | |
393 /* avoid storing the frame when the list is empty and we haven't yet | |
394 provided a frame for output */ | |
395 assert(!ctx->coded_frame_list); | |
396 cx_pktcpy(&cx_frame, pkt); | |
397 size = storeframe(avctx, &cx_frame, buf, buf_size, coded_frame); | |
398 if (size < 0) | |
399 return AVERROR(EINVAL); | |
400 } else { | |
401 struct FrameListData *cx_frame = | |
402 av_malloc(sizeof(struct FrameListData)); | |
403 | |
404 if (!cx_frame) { | |
405 av_log(avctx, AV_LOG_ERROR, | |
406 "Frame queue element alloc failed\n"); | |
407 return AVERROR(ENOMEM); | |
408 } | |
409 cx_pktcpy(cx_frame, pkt); | |
410 cx_frame->buf = av_malloc(cx_frame->sz); | |
411 | |
412 if (!cx_frame->buf) { | |
413 av_log(avctx, AV_LOG_ERROR, | |
414 "Data buffer alloc (%zu bytes) failed\n", | |
415 cx_frame->sz); | |
416 return AVERROR(ENOMEM); | |
417 } | |
418 memcpy(cx_frame->buf, pkt->data.frame.buf, pkt->data.frame.sz); | |
419 coded_frame_add(&ctx->coded_frame_list, cx_frame); | |
420 } | |
421 break; | |
422 case VPX_CODEC_STATS_PKT: { | |
423 struct vpx_fixed_buf *stats = &ctx->twopass_stats; | |
424 stats->buf = av_realloc(stats->buf, | |
425 stats->sz + pkt->data.twopass_stats.sz); | |
426 if (!stats->buf) { | |
427 av_log(avctx, AV_LOG_ERROR, "Stat buffer realloc failed\n"); | |
428 return AVERROR(ENOMEM); | |
429 } | |
430 memcpy((uint8_t*)stats->buf + stats->sz, | |
431 pkt->data.twopass_stats.buf, pkt->data.twopass_stats.sz); | |
432 stats->sz += pkt->data.twopass_stats.sz; | |
433 break; | |
434 } | |
435 case VPX_CODEC_PSNR_PKT: //FIXME add support for CODEC_FLAG_PSNR | |
436 case VPX_CODEC_CUSTOM_PKT: | |
437 //ignore unsupported/unrecognized packet types | |
438 break; | |
439 } | |
440 } | |
441 | |
442 return size; | |
443 } | |
444 | |
445 static int vp8_encode(AVCodecContext *avctx, uint8_t *buf, int buf_size, | |
446 void *data) | |
447 { | |
448 VP8Context *ctx = avctx->priv_data; | |
449 AVFrame *frame = data; | |
450 struct vpx_image *rawimg = NULL; | |
451 int64_t timestamp = 0; | |
452 int res, coded_size; | |
453 | |
454 if (frame) { | |
455 rawimg = &ctx->rawimg; | |
456 rawimg->planes[VPX_PLANE_Y] = frame->data[0]; | |
457 rawimg->planes[VPX_PLANE_U] = frame->data[1]; | |
458 rawimg->planes[VPX_PLANE_V] = frame->data[2]; | |
459 rawimg->stride[VPX_PLANE_Y] = frame->linesize[0]; | |
460 rawimg->stride[VPX_PLANE_U] = frame->linesize[1]; | |
461 rawimg->stride[VPX_PLANE_V] = frame->linesize[2]; | |
462 timestamp = frame->pts; | |
463 } | |
464 | |
465 res = vpx_codec_encode(&ctx->encoder, rawimg, timestamp, | |
466 avctx->ticks_per_frame, 0, ctx->deadline); | |
467 if (res != VPX_CODEC_OK) { | |
468 log_encoder_error(avctx, "Error encoding frame"); | |
469 return AVERROR_INVALIDDATA; | |
470 } | |
471 coded_size = queue_frames(avctx, buf, buf_size, avctx->coded_frame); | |
472 | |
473 if (!frame && avctx->flags & CODEC_FLAG_PASS1) { | |
11846 | 474 unsigned int b64_size = AV_BASE64_SIZE(ctx->twopass_stats.sz); |
11821 | 475 |
476 avctx->stats_out = av_malloc(b64_size); | |
477 if (!avctx->stats_out) { | |
478 av_log(avctx, AV_LOG_ERROR, "Stat buffer alloc (%d bytes) failed\n", | |
479 b64_size); | |
480 return AVERROR(ENOMEM); | |
481 } | |
482 av_base64_encode(avctx->stats_out, b64_size, ctx->twopass_stats.buf, | |
483 ctx->twopass_stats.sz); | |
484 } | |
485 return coded_size; | |
486 } | |
487 | |
488 AVCodec libvpx_encoder = { | |
489 "libvpx", | |
490 AVMEDIA_TYPE_VIDEO, | |
491 CODEC_ID_VP8, | |
492 sizeof(VP8Context), | |
493 vp8_init, | |
494 vp8_encode, | |
495 vp8_free, | |
496 NULL, | |
497 CODEC_CAP_DELAY, | |
498 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE}, | |
499 .long_name = NULL_IF_CONFIG_SMALL("libvpx VP8"), | |
500 }; |