blob: 82e12179a6b5c9d366c2f71bc86ea8780db01f43
1 | /* |
2 | * Copyright (c) 2001 Fabrice Bellard |
3 | * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at> |
4 | * |
5 | * This file is part of FFmpeg. |
6 | * |
7 | * FFmpeg is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either |
10 | * version 2.1 of the License, or (at your option) any later version. |
11 | * |
12 | * FFmpeg is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * Lesser General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Lesser General Public |
18 | * License along with FFmpeg; if not, write to the Free Software |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | */ |
21 | |
22 | /** |
23 | * @file |
24 | * Options definition for AVCodecContext. |
25 | */ |
26 | |
27 | #include "avcodec.h" |
28 | #include "internal.h" |
29 | #include "libavutil/avassert.h" |
30 | #include "libavutil/internal.h" |
31 | #include "libavutil/mem.h" |
32 | #include "libavutil/opt.h" |
33 | #include <float.h> /* FLT_MIN, FLT_MAX */ |
34 | #include <string.h> |
35 | |
36 | FF_DISABLE_DEPRECATION_WARNINGS |
37 | #include "options_table.h" |
38 | FF_ENABLE_DEPRECATION_WARNINGS |
39 | |
40 | static const char* context_to_name(void* ptr) { |
41 | AVCodecContext *avc= ptr; |
42 | |
43 | if(avc && avc->codec && avc->codec->name) |
44 | return avc->codec->name; |
45 | else |
46 | return "NULL"; |
47 | } |
48 | |
49 | static void *codec_child_next(void *obj, void *prev) |
50 | { |
51 | AVCodecContext *s = obj; |
52 | if (!prev && s->codec && s->codec->priv_class && s->priv_data) |
53 | return s->priv_data; |
54 | return NULL; |
55 | } |
56 | |
57 | static const AVClass *codec_child_class_next(const AVClass *prev) |
58 | { |
59 | AVCodec *c = NULL; |
60 | |
61 | /* find the codec that corresponds to prev */ |
62 | while (prev && (c = av_codec_next(c))) |
63 | if (c->priv_class == prev) |
64 | break; |
65 | |
66 | /* find next codec with priv options */ |
67 | while (c = av_codec_next(c)) |
68 | if (c->priv_class) |
69 | return c->priv_class; |
70 | return NULL; |
71 | } |
72 | |
73 | static AVClassCategory get_category(void *ptr) |
74 | { |
75 | AVCodecContext* avctx = ptr; |
76 | if(avctx->codec && avctx->codec->decode) return AV_CLASS_CATEGORY_DECODER; |
77 | else return AV_CLASS_CATEGORY_ENCODER; |
78 | } |
79 | |
80 | static const AVClass av_codec_context_class = { |
81 | .class_name = "AVCodecContext", |
82 | .item_name = context_to_name, |
83 | .option = avcodec_options, |
84 | .version = LIBAVUTIL_VERSION_INT, |
85 | .log_level_offset_offset = offsetof(AVCodecContext, log_level_offset), |
86 | .child_next = codec_child_next, |
87 | .child_class_next = codec_child_class_next, |
88 | .category = AV_CLASS_CATEGORY_ENCODER, |
89 | .get_category = get_category, |
90 | }; |
91 | |
92 | static int init_context_defaults(AVCodecContext *s, const AVCodec *codec) |
93 | { |
94 | int flags=0; |
95 | memset(s, 0, sizeof(AVCodecContext)); |
96 | |
97 | s->av_class = &av_codec_context_class; |
98 | |
99 | s->codec_type = codec ? codec->type : AVMEDIA_TYPE_UNKNOWN; |
100 | if (codec) { |
101 | s->codec = codec; |
102 | s->codec_id = codec->id; |
103 | } |
104 | |
105 | if(s->codec_type == AVMEDIA_TYPE_AUDIO) |
106 | flags= AV_OPT_FLAG_AUDIO_PARAM; |
107 | else if(s->codec_type == AVMEDIA_TYPE_VIDEO) |
108 | flags= AV_OPT_FLAG_VIDEO_PARAM; |
109 | else if(s->codec_type == AVMEDIA_TYPE_SUBTITLE) |
110 | flags= AV_OPT_FLAG_SUBTITLE_PARAM; |
111 | av_opt_set_defaults2(s, flags, flags); |
112 | |
113 | s->time_base = (AVRational){0,1}; |
114 | s->framerate = (AVRational){ 0, 1 }; |
115 | s->pkt_timebase = (AVRational){ 0, 1 }; |
116 | s->get_buffer2 = avcodec_default_get_buffer2; |
117 | s->get_format = avcodec_default_get_format; |
118 | s->execute = avcodec_default_execute; |
119 | s->execute2 = avcodec_default_execute2; |
120 | s->sample_aspect_ratio = (AVRational){0,1}; |
121 | s->pix_fmt = AV_PIX_FMT_NONE; |
122 | s->sw_pix_fmt = AV_PIX_FMT_NONE; |
123 | s->sample_fmt = AV_SAMPLE_FMT_NONE; |
124 | |
125 | s->reordered_opaque = AV_NOPTS_VALUE; |
126 | if(codec && codec->priv_data_size){ |
127 | if(!s->priv_data){ |
128 | s->priv_data= av_mallocz(codec->priv_data_size); |
129 | if (!s->priv_data) { |
130 | return AVERROR(ENOMEM); |
131 | } |
132 | } |
133 | if(codec->priv_class){ |
134 | *(const AVClass**)s->priv_data = codec->priv_class; |
135 | av_opt_set_defaults(s->priv_data); |
136 | } |
137 | } |
138 | if (codec && codec->defaults) { |
139 | int ret; |
140 | const AVCodecDefault *d = codec->defaults; |
141 | while (d->key) { |
142 | ret = av_opt_set(s, d->key, d->value, 0); |
143 | av_assert0(ret >= 0); |
144 | d++; |
145 | } |
146 | } |
147 | return 0; |
148 | } |
149 | |
150 | #if FF_API_GET_CONTEXT_DEFAULTS |
151 | int avcodec_get_context_defaults3(AVCodecContext *s, const AVCodec *codec) |
152 | { |
153 | return init_context_defaults(s, codec); |
154 | } |
155 | #endif |
156 | |
157 | AVCodecContext *avcodec_alloc_context3(const AVCodec *codec) |
158 | { |
159 | AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext)); |
160 | |
161 | if (!avctx) |
162 | return NULL; |
163 | |
164 | if (init_context_defaults(avctx, codec) < 0) { |
165 | av_free(avctx); |
166 | return NULL; |
167 | } |
168 | |
169 | return avctx; |
170 | } |
171 | |
172 | void avcodec_free_context(AVCodecContext **pavctx) |
173 | { |
174 | AVCodecContext *avctx = *pavctx; |
175 | |
176 | if (!avctx) |
177 | return; |
178 | |
179 | avcodec_close(avctx); |
180 | |
181 | av_freep(&avctx->extradata); |
182 | av_freep(&avctx->subtitle_header); |
183 | av_freep(&avctx->intra_matrix); |
184 | av_freep(&avctx->inter_matrix); |
185 | av_freep(&avctx->rc_override); |
186 | |
187 | av_freep(pavctx); |
188 | } |
189 | |
190 | #if FF_API_COPY_CONTEXT |
191 | static void copy_context_reset(AVCodecContext *avctx) |
192 | { |
193 | int i; |
194 | |
195 | av_opt_free(avctx); |
196 | #if FF_API_CODED_FRAME |
197 | FF_DISABLE_DEPRECATION_WARNINGS |
198 | av_frame_free(&avctx->coded_frame); |
199 | FF_ENABLE_DEPRECATION_WARNINGS |
200 | #endif |
201 | av_freep(&avctx->rc_override); |
202 | av_freep(&avctx->intra_matrix); |
203 | av_freep(&avctx->inter_matrix); |
204 | av_freep(&avctx->extradata); |
205 | av_freep(&avctx->subtitle_header); |
206 | av_buffer_unref(&avctx->hw_frames_ctx); |
207 | av_buffer_unref(&avctx->hw_device_ctx); |
208 | for (i = 0; i < avctx->nb_coded_side_data; i++) |
209 | av_freep(&avctx->coded_side_data[i].data); |
210 | av_freep(&avctx->coded_side_data); |
211 | avctx->subtitle_header_size = 0; |
212 | avctx->nb_coded_side_data = 0; |
213 | avctx->extradata_size = 0; |
214 | } |
215 | |
216 | int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src) |
217 | { |
218 | const AVCodec *orig_codec = dest->codec; |
219 | uint8_t *orig_priv_data = dest->priv_data; |
220 | |
221 | if (avcodec_is_open(dest)) { // check that the dest context is uninitialized |
222 | av_log(dest, AV_LOG_ERROR, |
223 | "Tried to copy AVCodecContext %p into already-initialized %p\n", |
224 | src, dest); |
225 | return AVERROR(EINVAL); |
226 | } |
227 | |
228 | copy_context_reset(dest); |
229 | |
230 | memcpy(dest, src, sizeof(*dest)); |
231 | av_opt_copy(dest, src); |
232 | |
233 | dest->priv_data = orig_priv_data; |
234 | dest->codec = orig_codec; |
235 | |
236 | if (orig_priv_data && src->codec && src->codec->priv_class && |
237 | dest->codec && dest->codec->priv_class) |
238 | av_opt_copy(orig_priv_data, src->priv_data); |
239 | |
240 | |
241 | /* set values specific to opened codecs back to their default state */ |
242 | dest->slice_offset = NULL; |
243 | dest->hwaccel = NULL; |
244 | dest->internal = NULL; |
245 | #if FF_API_CODED_FRAME |
246 | FF_DISABLE_DEPRECATION_WARNINGS |
247 | dest->coded_frame = NULL; |
248 | FF_ENABLE_DEPRECATION_WARNINGS |
249 | #endif |
250 | |
251 | /* reallocate values that should be allocated separately */ |
252 | dest->extradata = NULL; |
253 | dest->coded_side_data = NULL; |
254 | dest->intra_matrix = NULL; |
255 | dest->inter_matrix = NULL; |
256 | dest->rc_override = NULL; |
257 | dest->subtitle_header = NULL; |
258 | dest->hw_frames_ctx = NULL; |
259 | dest->hw_device_ctx = NULL; |
260 | dest->nb_coded_side_data = 0; |
261 | |
262 | #define alloc_and_copy_or_fail(obj, size, pad) \ |
263 | if (src->obj && size > 0) { \ |
264 | dest->obj = av_malloc(size + pad); \ |
265 | if (!dest->obj) \ |
266 | goto fail; \ |
267 | memcpy(dest->obj, src->obj, size); \ |
268 | if (pad) \ |
269 | memset(((uint8_t *) dest->obj) + size, 0, pad); \ |
270 | } |
271 | alloc_and_copy_or_fail(extradata, src->extradata_size, |
272 | AV_INPUT_BUFFER_PADDING_SIZE); |
273 | dest->extradata_size = src->extradata_size; |
274 | alloc_and_copy_or_fail(intra_matrix, 64 * sizeof(int16_t), 0); |
275 | alloc_and_copy_or_fail(inter_matrix, 64 * sizeof(int16_t), 0); |
276 | alloc_and_copy_or_fail(rc_override, src->rc_override_count * sizeof(*src->rc_override), 0); |
277 | alloc_and_copy_or_fail(subtitle_header, src->subtitle_header_size, 1); |
278 | av_assert0(dest->subtitle_header_size == src->subtitle_header_size); |
279 | #undef alloc_and_copy_or_fail |
280 | |
281 | if (src->hw_frames_ctx) { |
282 | dest->hw_frames_ctx = av_buffer_ref(src->hw_frames_ctx); |
283 | if (!dest->hw_frames_ctx) |
284 | goto fail; |
285 | } |
286 | |
287 | return 0; |
288 | |
289 | fail: |
290 | copy_context_reset(dest); |
291 | return AVERROR(ENOMEM); |
292 | } |
293 | #endif |
294 | |
295 | const AVClass *avcodec_get_class(void) |
296 | { |
297 | return &av_codec_context_class; |
298 | } |
299 | |
300 | #define FOFFSET(x) offsetof(AVFrame,x) |
301 | |
302 | static const AVOption frame_options[]={ |
303 | {"best_effort_timestamp", "", FOFFSET(best_effort_timestamp), AV_OPT_TYPE_INT64, {.i64 = AV_NOPTS_VALUE }, INT64_MIN, INT64_MAX, 0}, |
304 | {"pkt_pos", "", FOFFSET(pkt_pos), AV_OPT_TYPE_INT64, {.i64 = -1 }, INT64_MIN, INT64_MAX, 0}, |
305 | {"pkt_size", "", FOFFSET(pkt_size), AV_OPT_TYPE_INT64, {.i64 = -1 }, INT64_MIN, INT64_MAX, 0}, |
306 | {"sample_aspect_ratio", "", FOFFSET(sample_aspect_ratio), AV_OPT_TYPE_RATIONAL, {.dbl = 0 }, 0, INT_MAX, 0}, |
307 | {"width", "", FOFFSET(width), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0}, |
308 | {"height", "", FOFFSET(height), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0}, |
309 | {"format", "", FOFFSET(format), AV_OPT_TYPE_INT, {.i64 = -1 }, 0, INT_MAX, 0}, |
310 | {"channel_layout", "", FOFFSET(channel_layout), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, 0}, |
311 | {"sample_rate", "", FOFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0}, |
312 | {NULL}, |
313 | }; |
314 | |
315 | static const AVClass av_frame_class = { |
316 | .class_name = "AVFrame", |
317 | .item_name = NULL, |
318 | .option = frame_options, |
319 | .version = LIBAVUTIL_VERSION_INT, |
320 | }; |
321 | |
322 | const AVClass *avcodec_get_frame_class(void) |
323 | { |
324 | return &av_frame_class; |
325 | } |
326 | |
327 | #define SROFFSET(x) offsetof(AVSubtitleRect,x) |
328 | |
329 | static const AVOption subtitle_rect_options[]={ |
330 | {"x", "", SROFFSET(x), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0}, |
331 | {"y", "", SROFFSET(y), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0}, |
332 | {"w", "", SROFFSET(w), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0}, |
333 | {"h", "", SROFFSET(h), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0}, |
334 | {"type", "", SROFFSET(type), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0}, |
335 | {"flags", "", SROFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, 0, 1, 0, "flags"}, |
336 | {"forced", "", SROFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, 0, 1, 0}, |
337 | {NULL}, |
338 | }; |
339 | |
340 | static const AVClass av_subtitle_rect_class = { |
341 | .class_name = "AVSubtitleRect", |
342 | .item_name = NULL, |
343 | .option = subtitle_rect_options, |
344 | .version = LIBAVUTIL_VERSION_INT, |
345 | }; |
346 | |
347 | const AVClass *avcodec_get_subtitle_rect_class(void) |
348 | { |
349 | return &av_subtitle_rect_class; |
350 | } |
351 | |
352 | #ifdef TEST |
353 | static int dummy_init(AVCodecContext *ctx) |
354 | { |
355 | //TODO: this code should set every possible pointer that could be set by codec and is not an option; |
356 | ctx->extradata_size = 8; |
357 | ctx->extradata = av_malloc(ctx->extradata_size); |
358 | return 0; |
359 | } |
360 | |
361 | static int dummy_close(AVCodecContext *ctx) |
362 | { |
363 | av_freep(&ctx->extradata); |
364 | ctx->extradata_size = 0; |
365 | return 0; |
366 | } |
367 | |
368 | static int dummy_encode(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, int *got_packet) |
369 | { |
370 | return AVERROR(ENOSYS); |
371 | } |
372 | |
373 | typedef struct Dummy12Context { |
374 | AVClass *av_class; |
375 | int num; |
376 | char* str; |
377 | } Dummy12Context; |
378 | |
379 | typedef struct Dummy3Context { |
380 | void *fake_av_class; |
381 | int num; |
382 | char* str; |
383 | } Dummy3Context; |
384 | |
385 | #define OFFSET(x) offsetof(Dummy12Context, x) |
386 | #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM |
387 | static const AVOption dummy_options[] = { |
388 | { "str", "set str", OFFSET(str), AV_OPT_TYPE_STRING, { .str = "i'm src default value" }, 0, 0, VE}, |
389 | { "num", "set num", OFFSET(num), AV_OPT_TYPE_INT, { .i64 = 1500100900 }, 0, INT_MAX, VE}, |
390 | { NULL }, |
391 | }; |
392 | |
393 | static const AVClass dummy_v1_class = { |
394 | .class_name = "dummy_v1_class", |
395 | .item_name = av_default_item_name, |
396 | .option = dummy_options, |
397 | .version = LIBAVUTIL_VERSION_INT, |
398 | }; |
399 | |
400 | static const AVClass dummy_v2_class = { |
401 | .class_name = "dummy_v2_class", |
402 | .item_name = av_default_item_name, |
403 | .option = dummy_options, |
404 | .version = LIBAVUTIL_VERSION_INT, |
405 | }; |
406 | |
407 | /* codec with options */ |
408 | static AVCodec dummy_v1_encoder = { |
409 | .name = "dummy_v1_codec", |
410 | .type = AVMEDIA_TYPE_VIDEO, |
411 | .id = AV_CODEC_ID_NONE - 1, |
412 | .encode2 = dummy_encode, |
413 | .init = dummy_init, |
414 | .close = dummy_close, |
415 | .priv_class = &dummy_v1_class, |
416 | .priv_data_size = sizeof(Dummy12Context), |
417 | }; |
418 | |
419 | /* codec with options, different class */ |
420 | static AVCodec dummy_v2_encoder = { |
421 | .name = "dummy_v2_codec", |
422 | .type = AVMEDIA_TYPE_VIDEO, |
423 | .id = AV_CODEC_ID_NONE - 2, |
424 | .encode2 = dummy_encode, |
425 | .init = dummy_init, |
426 | .close = dummy_close, |
427 | .priv_class = &dummy_v2_class, |
428 | .priv_data_size = sizeof(Dummy12Context), |
429 | }; |
430 | |
431 | /* codec with priv data, but no class */ |
432 | static AVCodec dummy_v3_encoder = { |
433 | .name = "dummy_v3_codec", |
434 | .type = AVMEDIA_TYPE_VIDEO, |
435 | .id = AV_CODEC_ID_NONE - 3, |
436 | .encode2 = dummy_encode, |
437 | .init = dummy_init, |
438 | .close = dummy_close, |
439 | .priv_data_size = sizeof(Dummy3Context), |
440 | }; |
441 | |
442 | /* codec without priv data */ |
443 | static AVCodec dummy_v4_encoder = { |
444 | .name = "dummy_v4_codec", |
445 | .type = AVMEDIA_TYPE_VIDEO, |
446 | .id = AV_CODEC_ID_NONE - 4, |
447 | .encode2 = dummy_encode, |
448 | .init = dummy_init, |
449 | .close = dummy_close, |
450 | }; |
451 | |
452 | static void test_copy_print_codec(const AVCodecContext *ctx) |
453 | { |
454 | printf("%-14s: %dx%d prv: %s", |
455 | ctx->codec ? ctx->codec->name : "NULL", |
456 | ctx->width, ctx->height, |
457 | ctx->priv_data ? "set" : "null"); |
458 | if (ctx->codec && ctx->codec->priv_class && ctx->codec->priv_data_size) { |
459 | int64_t i64; |
460 | char *str = NULL; |
461 | av_opt_get_int(ctx->priv_data, "num", 0, &i64); |
462 | av_opt_get(ctx->priv_data, "str", 0, (uint8_t**)&str); |
463 | printf(" opts: %"PRId64" %s", i64, str); |
464 | av_free(str); |
465 | } |
466 | printf("\n"); |
467 | } |
468 | |
469 | static void test_copy(const AVCodec *c1, const AVCodec *c2) |
470 | { |
471 | AVCodecContext *ctx1, *ctx2; |
472 | printf("%s -> %s\nclosed:\n", c1 ? c1->name : "NULL", c2 ? c2->name : "NULL"); |
473 | ctx1 = avcodec_alloc_context3(c1); |
474 | ctx2 = avcodec_alloc_context3(c2); |
475 | ctx1->width = ctx1->height = 128; |
476 | if (ctx2->codec && ctx2->codec->priv_class && ctx2->codec->priv_data_size) { |
477 | av_opt_set(ctx2->priv_data, "num", "667", 0); |
478 | av_opt_set(ctx2->priv_data, "str", "i'm dest value before copy", 0); |
479 | } |
480 | avcodec_copy_context(ctx2, ctx1); |
481 | test_copy_print_codec(ctx1); |
482 | test_copy_print_codec(ctx2); |
483 | if (ctx1->codec) { |
484 | printf("opened:\n"); |
485 | avcodec_open2(ctx1, ctx1->codec, NULL); |
486 | if (ctx2->codec && ctx2->codec->priv_class && ctx2->codec->priv_data_size) { |
487 | av_opt_set(ctx2->priv_data, "num", "667", 0); |
488 | av_opt_set(ctx2->priv_data, "str", "i'm dest value before copy", 0); |
489 | } |
490 | avcodec_copy_context(ctx2, ctx1); |
491 | test_copy_print_codec(ctx1); |
492 | test_copy_print_codec(ctx2); |
493 | avcodec_close(ctx1); |
494 | } |
495 | avcodec_free_context(&ctx1); |
496 | avcodec_free_context(&ctx2); |
497 | } |
498 | |
499 | int main(void) |
500 | { |
501 | AVCodec *dummy_codec[] = { |
502 | &dummy_v1_encoder, |
503 | &dummy_v2_encoder, |
504 | &dummy_v3_encoder, |
505 | &dummy_v4_encoder, |
506 | NULL, |
507 | }; |
508 | int i, j; |
509 | |
510 | for (i = 0; dummy_codec[i]; i++) |
511 | avcodec_register(dummy_codec[i]); |
512 | |
513 | printf("testing avcodec_copy_context()\n"); |
514 | for (i = 0; i < FF_ARRAY_ELEMS(dummy_codec); i++) |
515 | for (j = 0; j < FF_ARRAY_ELEMS(dummy_codec); j++) |
516 | test_copy(dummy_codec[i], dummy_codec[j]); |
517 | return 0; |
518 | } |
519 | #endif |
520 |