From d103218046883cb9e7f6e83af53b0982fee370ba Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Wed, 31 Mar 2010 20:40:49 +0000 Subject: [PATCH] Add avcodec_copy_context(). Originally committed as revision 22750 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavcodec/avcodec.h | 13 ++++++++++ libavcodec/options.c | 60 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 12d9b3d47c..251e47dbc6 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -3258,6 +3258,19 @@ AVCodecContext *avcodec_alloc_context(void); * we WILL change its arguments and name a few times! */ AVCodecContext *avcodec_alloc_context2(enum AVMediaType); +/** + * Copy the settings of the source AVCodecContext into the destination + * AVCodecContext. The resulting destination codec context will be + * unopened, i.e. you are required to call avcodec_open() before you + * can use this AVCodecContext to decode/encode video/audio data. + * + * @param dest target codec context, should be initialized with + * avcodec_alloc_context(), but otherwise uninitialized + * @param src source codec context + * @return AVERROR() on error (e.g. memory allocation error), 0 on success + */ +int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src); + /** * Sets the fields of the given AVFrame to default values. * diff --git a/libavcodec/options.c b/libavcodec/options.c index 89b25483c2..04fd3ba496 100644 --- a/libavcodec/options.c +++ b/libavcodec/options.c @@ -471,3 +471,63 @@ AVCodecContext *avcodec_alloc_context(void){ return avcodec_alloc_context2(AVMEDIA_TYPE_UNKNOWN); } +int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src) +{ + if (dest->codec) { // check that the dest context is uninitialized + av_log(dest, AV_LOG_ERROR, + "Tried to copy AVCodecContext %p into already-initialized %p\n", + src, dest); + return AVERROR(EINVAL); + } + memcpy(dest, src, sizeof(*dest)); + + /* set values specific to opened codecs back to their default state */ + dest->priv_data = NULL; + dest->codec = NULL; + dest->palctrl = NULL; + dest->slice_offset = NULL; + dest->internal_buffer = NULL; + dest->hwaccel = NULL; + dest->execute = NULL; + dest->execute2 = NULL; + dest->reget_buffer = NULL; + dest->thread_opaque = NULL; + + /* reallocate values that should be allocated separately */ + dest->rc_eq = NULL; + dest->extradata = NULL; + dest->intra_matrix = NULL; + dest->inter_matrix = NULL; + dest->rc_override = NULL; + if (src->rc_eq) { + dest->rc_eq = av_strdup(src->rc_eq); + if (!dest->rc_eq) + return AVERROR(ENOMEM); + } + +#define alloc_and_copy_or_fail(obj, size, pad) \ + if (src->obj && size > 0) { \ + dest->obj = av_malloc(size + pad); \ + if (!dest->obj) \ + goto fail; \ + memcpy(dest->obj, src->obj, size); \ + if (pad) \ + memset(((uint8_t *) dest->obj) + size, 0, pad); \ + } + alloc_and_copy_or_fail(extradata, src->extradata_size, + FF_INPUT_BUFFER_PADDING_SIZE); + alloc_and_copy_or_fail(intra_matrix, 64 * sizeof(int16_t), 0); + alloc_and_copy_or_fail(inter_matrix, 64 * sizeof(int16_t), 0); + alloc_and_copy_or_fail(rc_override, src->rc_override_count * sizeof(*src->rc_override), 0); +#undef alloc_and_copy_or_fail + + return 0; + +fail: + av_freep(&dest->rc_override); + av_freep(&dest->intra_matrix); + av_freep(&dest->inter_matrix); + av_freep(&dest->extradata); + av_freep(&dest->rc_eq); + return AVERROR(ENOMEM); +}