diff options
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | avconv.h | 2 | ||||
-rw-r--r-- | avconv_opt.c | 3 | ||||
-rw-r--r-- | avconv_vda.c | 134 | ||||
-rw-r--r-- | doc/avconv.texi | 3 |
5 files changed, 143 insertions, 0 deletions
@@ -76,6 +76,7 @@ $(foreach prog,$(AVBASENAMES),$(eval OBJS-$(prog) += cmdutils.o)) OBJS-avconv += avconv_opt.o avconv_filter.o OBJS-avconv-$(HAVE_VDPAU_X11) += avconv_vdpau.o OBJS-avconv-$(HAVE_DXVA2_LIB) += avconv_dxva2.o +OBJS-avconv-$(CONFIG_VDA) += avconv_vda.o TESTTOOLS = audiogen videogen rotozoom tiny_psnr base64 HOSTPROGS := $(TESTTOOLS:%=tests/%) doc/print_options @@ -53,6 +53,7 @@ enum HWAccelID { HWACCEL_AUTO, HWACCEL_VDPAU, HWACCEL_DXVA2, + HWACCEL_VDA, }; typedef struct HWAccel { @@ -423,5 +424,6 @@ int avconv_parse_options(int argc, char **argv); int vdpau_init(AVCodecContext *s); int dxva2_init(AVCodecContext *s); +int vda_init(AVCodecContext *s); #endif /* AVCONV_H */ diff --git a/avconv_opt.c b/avconv_opt.c index f400e75..12d6760 100644 --- a/avconv_opt.c +++ b/avconv_opt.c @@ -60,6 +60,9 @@ const HWAccel hwaccels[] = { #if HAVE_DXVA2_LIB { "dxva2", dxva2_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD }, #endif +#if CONFIG_VDA + { "vda", vda_init, HWACCEL_VDA, AV_PIX_FMT_VDA }, +#endif { 0 }, }; diff --git a/avconv_vda.c b/avconv_vda.c new file mode 100644 index 0000000..40f87c4 --- /dev/null +++ b/avconv_vda.c @@ -0,0 +1,134 @@ +/* + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/avcodec.h" +#include "libavcodec/vda.h" +#include "libavutil/imgutils.h" + +#include "avconv.h" + +typedef struct VDAContext { + AVFrame *tmp_frame; +} VDAContext; + +static int vda_retrieve_data(AVCodecContext *s, AVFrame *frame) +{ + InputStream *ist = s->opaque; + VDAContext *vda = ist->hwaccel_ctx; + CVPixelBufferRef pixbuf = (CVPixelBufferRef)frame->data[3]; + OSType pixel_format = CVPixelBufferGetPixelFormatType(pixbuf); + CVReturn err; + uint8_t *data[4] = { 0 }; + int linesize[4] = { 0 }; + int planes, ret, i; + + av_frame_unref(vda->tmp_frame); + + switch (pixel_format) { + case kCVPixelFormatType_420YpCbCr8Planar: vda->tmp_frame->format = AV_PIX_FMT_YUV420P; break; + case kCVPixelFormatType_422YpCbCr8: vda->tmp_frame->format = AV_PIX_FMT_UYVY422; break; + default: + av_log(NULL, AV_LOG_ERROR, + "Unsupported pixel format: %u\n", pixel_format); + return AVERROR(ENOSYS); + } + + vda->tmp_frame->width = frame->width; + vda->tmp_frame->height = frame->height; + ret = av_frame_get_buffer(vda->tmp_frame, 32); + if (ret < 0) + return ret; + + err = CVPixelBufferLockBaseAddress(pixbuf, kCVPixelBufferLock_ReadOnly); + if (err != kCVReturnSuccess) { + av_log(NULL, AV_LOG_ERROR, "Error locking the pixel buffer.\n"); + return AVERROR_UNKNOWN; + } + + if (CVPixelBufferIsPlanar(pixbuf)) { + + planes = CVPixelBufferGetPlaneCount(pixbuf); + for (i = 0; i < planes; i++) { + data[i] = CVPixelBufferGetBaseAddressOfPlane(pixbuf, i); + linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(pixbuf, i); + } + } else { + data[0] = CVPixelBufferGetBaseAddress(pixbuf); + linesize[0] = CVPixelBufferGetBytesPerRow(pixbuf); + } + + av_image_copy(vda->tmp_frame->data, vda->tmp_frame->linesize, + data, linesize, vda->tmp_frame->format, + frame->width, frame->height); + + ret = av_frame_copy_props(vda->tmp_frame, frame); + if (ret < 0) + return ret; + + av_frame_unref(frame); + av_frame_move_ref(frame, vda->tmp_frame); + + return 0; +} + +static void vda_uninit(AVCodecContext *s) +{ + InputStream *ist = s->opaque; + VDAContext *vda = ist->hwaccel_ctx; + + ist->hwaccel_uninit = NULL; + ist->hwaccel_retrieve_data = NULL; + + av_frame_free(&vda->tmp_frame); + + av_vda_default_free(s); + av_freep(&ist->hwaccel_ctx); +} + +int vda_init(AVCodecContext *s) +{ + InputStream *ist = s->opaque; + int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR; + VDAContext *vda; + int ret; + + vda = av_mallocz(sizeof(*vda)); + if (!vda) + return AVERROR(ENOMEM); + + ist->hwaccel_ctx = vda; + ist->hwaccel_uninit = vda_uninit; + ist->hwaccel_retrieve_data = vda_retrieve_data; + + vda->tmp_frame = av_frame_alloc(); + if (!vda->tmp_frame) { + ret = AVERROR(ENOMEM); + goto fail; + } + + ret = av_vda_default_init(s); + if (ret < 0) { + av_log(NULL, loglevel, "Error creating VDA decoder.\n"); + goto fail; + } + + return 0; +fail: + vda_uninit(s); + return ret; +} diff --git a/doc/avconv.texi b/doc/avconv.texi index f3bb605..6efec55 100644 --- a/doc/avconv.texi +++ b/doc/avconv.texi @@ -580,6 +580,9 @@ Do not use any hardware acceleration (the default). @item auto Automatically select the hardware acceleration method. +@item vda +Use Apple VDA hardware acceleration. + @item vdpau Use VDPAU (Video Decode and Presentation API for Unix) hardware acceleration. |