diff --git a/doc/APIchanges b/doc/APIchanges index c9464d8e95..0f6aed3d9b 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2012-10-22 API changes, most recent first: +2014-xx-xx - xxxxxxx - lavu 53.05.0 - frame.h + Add av_frame_copy() for copying the frame data. + 2014-02-xx - xxxxxxx - lswr 0.18.100 - swresample.h Add swr_is_initialized() for checking whether a resample context is initialized. diff --git a/libavutil/frame.c b/libavutil/frame.c index 75a1c28347..9b4ecfcc0f 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -271,16 +271,11 @@ int av_frame_ref(AVFrame *dst, const AVFrame *src) if (ret < 0) return ret; - if (src->nb_samples) { - int ch = src->channels; - CHECK_CHANNELS_CONSISTENCY(src); - av_samples_copy(dst->extended_data, src->extended_data, 0, 0, - dst->nb_samples, ch, dst->format); - } else { - av_image_copy(dst->data, dst->linesize, src->data, src->linesize, - dst->format, dst->width, dst->height); - } - return 0; + ret = av_frame_copy(dst, src); + if (ret < 0) + av_frame_unref(dst); + + return ret; } /* ref the buffers */ @@ -424,14 +419,10 @@ int av_frame_make_writable(AVFrame *frame) if (ret < 0) return ret; - if (tmp.nb_samples) { - int ch = tmp.channels; - CHECK_CHANNELS_CONSISTENCY(&tmp); - av_samples_copy(tmp.extended_data, frame->extended_data, 0, 0, - frame->nb_samples, ch, frame->format); - } else { - av_image_copy(tmp.data, tmp.linesize, frame->data, frame->linesize, - frame->format, frame->width, frame->height); + ret = av_frame_copy(&tmp, frame); + if (ret < 0) { + av_frame_unref(&tmp); + return ret; } ret = av_frame_copy_props(&tmp, frame); @@ -592,3 +583,61 @@ AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, } return NULL; } + +static int frame_copy_video(AVFrame *dst, const AVFrame *src) +{ + const uint8_t *src_data[4]; + int i, planes; + + if (dst->width != src->width || + dst->height != src->height) + return AVERROR(EINVAL); + + planes = av_pix_fmt_count_planes(dst->format); + for (i = 0; i < planes; i++) + if (!dst->data[i] || !src->data[i]) + return AVERROR(EINVAL); + + memcpy(src_data, src->data, sizeof(src_data)); + av_image_copy(dst->data, dst->linesize, + src_data, src->linesize, + dst->format, dst->width, dst->height); + + return 0; +} + +static int frame_copy_audio(AVFrame *dst, const AVFrame *src) +{ + int planar = av_sample_fmt_is_planar(dst->format); + int channels = dst->channels; + int planes = planar ? channels : 1; + int i; + + if (dst->nb_samples != src->nb_samples || + dst->channel_layout != src->channel_layout) + return AVERROR(EINVAL); + + CHECK_CHANNELS_CONSISTENCY(src); + + for (i = 0; i < planes; i++) + if (!dst->extended_data[i] || !src->extended_data[i]) + return AVERROR(EINVAL); + + av_samples_copy(dst->extended_data, src->extended_data, 0, 0, + dst->nb_samples, channels, dst->format); + + return 0; +} + +int av_frame_copy(AVFrame *dst, const AVFrame *src) +{ + if (dst->format != src->format || dst->format < 0) + return AVERROR(EINVAL); + + if (dst->width > 0 && dst->height > 0) + return frame_copy_video(dst, src); + else if (dst->nb_samples > 0 && dst->channel_layout) + return frame_copy_audio(dst, src); + + return AVERROR(EINVAL); +} diff --git a/libavutil/frame.h b/libavutil/frame.h index b423f67996..0cb5fb72ae 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -673,6 +673,19 @@ int av_frame_is_writable(AVFrame *frame); */ int av_frame_make_writable(AVFrame *frame); +/** + * Copy the frame data from src to dst. + * + * This function does not allocate anything, dst must be already initialized and + * allocated with the same parameters as src. + * + * This function only copies the frame data (i.e. the contents of the data / + * extended data arrays), not any other properties. + * + * @return >= 0 on success, a negative AVERROR on error. + */ +int av_frame_copy(AVFrame *dst, const AVFrame *src); + /** * Copy only "metadata" fields from src to dst. * diff --git a/libavutil/version.h b/libavutil/version.h index e3b822c01f..7f093cd583 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -56,7 +56,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 52 -#define LIBAVUTIL_VERSION_MINOR 65 +#define LIBAVUTIL_VERSION_MINOR 66 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \