annotate libvpxenc.c @ 12329:6644e439130d libavcodec

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