diff options
author | Derek Buitenhuis <derek.buitenhuis@gmail.com> | 2012-03-05 15:29:23 -0500 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-03-05 22:25:49 +0100 |
commit | 01606d10e600c4794d89490e731c321fb73a5141 (patch) | |
tree | 7b26f4bb99a3e43dc4acd9182557c3a3463fa93b /libavcodec | |
parent | d6e4e69a4993e8f2fe1f7e8227ac388039d886d2 (diff) | |
download | ffmpeg-01606d10e600c4794d89490e731c321fb73a5141.tar.gz |
libutvideo: Add Ut Video encoder wrapper
All colorspaces are supported.
Renamed libutvideo.cpp to libutvideodec.cpp.
Signed-off-by: Derek Buitenhuis <derek.buitenhuis@gmail.com>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/Makefile | 3 | ||||
-rw-r--r-- | libavcodec/allcodecs.c | 2 | ||||
-rw-r--r-- | libavcodec/libutvideodec.cpp (renamed from libavcodec/libutvideo.cpp) | 0 | ||||
-rw-r--r-- | libavcodec/libutvideoenc.cpp | 241 | ||||
-rw-r--r-- | libavcodec/version.h | 2 |
5 files changed, 245 insertions, 3 deletions
diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 433ae4867e..2e11dc89a2 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -647,7 +647,8 @@ OBJS-$(CONFIG_LIBSPEEX_DECODER) += libspeexdec.o OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o OBJS-$(CONFIG_LIBSTAGEFRIGHT_H264_DECODER)+= libstagefright.o OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o -OBJS-$(CONFIG_LIBUTVIDEO_DECODER) += libutvideo.o +OBJS-$(CONFIG_LIBUTVIDEO_DECODER) += libutvideodec.o +OBJS-$(CONFIG_LIBUTVIDEO_ENCODER) += libutvideoenc.o OBJS-$(CONFIG_LIBVO_AACENC_ENCODER) += libvo-aacenc.o mpeg4audio.o OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbis.o vorbis_data.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index c8cfbb53a8..52a67f34bd 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -412,7 +412,7 @@ void avcodec_register_all(void) REGISTER_ENCDEC (LIBSPEEX, libspeex); REGISTER_DECODER (LIBSTAGEFRIGHT_H264, libstagefright_h264); REGISTER_ENCODER (LIBTHEORA, libtheora); - REGISTER_DECODER (LIBUTVIDEO, libutvideo); + REGISTER_ENCDEC (LIBUTVIDEO, libutvideo); REGISTER_ENCODER (LIBVO_AACENC, libvo_aacenc); REGISTER_ENCODER (LIBVO_AMRWBENC, libvo_amrwbenc); REGISTER_ENCODER (LIBVORBIS, libvorbis); diff --git a/libavcodec/libutvideo.cpp b/libavcodec/libutvideodec.cpp index 443a77ea9d..443a77ea9d 100644 --- a/libavcodec/libutvideo.cpp +++ b/libavcodec/libutvideodec.cpp diff --git a/libavcodec/libutvideoenc.cpp b/libavcodec/libutvideoenc.cpp new file mode 100644 index 0000000000..564ece209a --- /dev/null +++ b/libavcodec/libutvideoenc.cpp @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2012 Derek Buitenhuis + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; + * version 2 of the License. + * + * FFmpeg 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Known FOURCCs: + * 'ULY0' (YCbCr 4:2:0), 'ULY2' (YCbCr 4:2:2), 'ULRG' (RGB), 'ULRA' (RGBA) + */ + +extern "C" { +#include "libavutil/avassert.h" +#include "avcodec.h" +#include "internal.h" +} + +#include "libutvideo.h" +#include "put_bits.h" + +static av_cold int utvideo_encode_init(AVCodecContext *avctx) +{ + UtVideoContext *utv = (UtVideoContext *)avctx->priv_data; + UtVideoExtra *info; + uint32_t flags, in_format; + + switch (avctx->pix_fmt) { + case PIX_FMT_YUV420P: + in_format = UTVF_YV12; + avctx->bits_per_coded_sample = 12; + avctx->codec_tag = MKTAG('U', 'L', 'Y', '0'); + break; + case PIX_FMT_YUYV422: + in_format = UTVF_YUYV; + avctx->bits_per_coded_sample = 16; + avctx->codec_tag = MKTAG('U', 'L', 'Y', '2'); + break; + case PIX_FMT_BGR24: + in_format = UTVF_RGB24_WIN; + avctx->bits_per_coded_sample = 24; + avctx->codec_tag = MKTAG('U', 'L', 'R', 'G'); + break; + case PIX_FMT_RGB32: + in_format = UTVF_RGB32_WIN; + avctx->bits_per_coded_sample = 32; + avctx->codec_tag = MKTAG('U', 'L', 'R', 'A'); + break; + default: + return AVERROR(EINVAL); + } + + /* Check before we alloc anything */ + if (avctx->prediction_method != 0 && avctx->prediction_method != 2) { + av_log(avctx, AV_LOG_ERROR, "Invalid prediction method.\n"); + return AVERROR(EINVAL); + } + + flags = ((avctx->prediction_method + 1) << 8) | (avctx->thread_count - 1); + + avctx->priv_data = utv; + avctx->coded_frame = avcodec_alloc_frame(); + + /* Alloc extradata buffer */ + info = (UtVideoExtra *)av_malloc(sizeof(*info)); + + if (info == NULL) { + av_log(avctx, AV_LOG_ERROR, "Could not allocate extradata buffer.\n"); + return AVERROR(ENOMEM); + } + + /* + * We use this buffer to hold the data that Ut Video returns, + * since we cannot decode planes separately with it. + */ + utv->buf_size = avpicture_get_size(avctx->pix_fmt, + avctx->width, avctx->height); + utv->buffer = (uint8_t *)av_malloc(utv->buf_size); + + if (utv->buffer == NULL) { + av_log(avctx, AV_LOG_ERROR, "Could not allocate output buffer.\n"); + return AVERROR(ENOMEM); + } + + /* + * Create a Ut Video instance. Since the function wants + * an "interface name" string, pass it the name of the lib. + */ + utv->codec = CCodec::CreateInstance(UNFCC(avctx->codec_tag), "libavcodec"); + + /* Initialize encoder */ + utv->codec->EncodeBegin(in_format, avctx->width, avctx->height, + CBGROSSWIDTH_WINDOWS); + + /* Get extradata from encoder */ + avctx->extradata_size = utv->codec->EncodeGetExtraDataSize(); + utv->codec->EncodeGetExtraData(info, avctx->extradata_size, in_format, + avctx->width, avctx->height, + CBGROSSWIDTH_WINDOWS); + avctx->extradata = (uint8_t *)info; + + /* Set flags */ + utv->codec->SetState(&flags, sizeof(flags)); + + return 0; +} + +static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pic, int *got_packet) +{ + UtVideoContext *utv = (UtVideoContext *)avctx->priv_data; + int w = avctx->width, h = avctx->height; + int ret, rgb_size, i; + bool keyframe; + uint8_t *y, *u, *v; + uint8_t *dst; + + /* Alloc buffer */ + if ((ret = ff_alloc_packet(pkt, utv->buf_size)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); + return ret; + } + + dst = pkt->data; + + /* Move input if needed data into Ut Video friendly buffer */ + switch (avctx->pix_fmt) { + case PIX_FMT_YUV420P: + y = utv->buffer; + u = y + w * h; + v = u + w * h / 4; + for (i = 0; i < h; i++) { + memcpy(y, pic->data[0] + i * pic->linesize[0], w); + y += w; + } + for (i = 0; i < h / 2; i++) { + memcpy(u, pic->data[2] + i * pic->linesize[2], w >> 1); + memcpy(v, pic->data[1] + i * pic->linesize[1], w >> 1); + u += w >> 1; + v += w >> 1; + } + break; + case PIX_FMT_YUYV422: + for (i = 0; i < h; i++) + memcpy(utv->buffer + i * (w << 1), + pic->data[0] + i * pic->linesize[0], w << 1); + break; + case PIX_FMT_BGR24: + case PIX_FMT_RGB32: + /* Ut Video takes bottom-up BGR */ + rgb_size = avctx->pix_fmt == PIX_FMT_BGR24 ? 3 : 4; + for (i = 0; i < h; i++) + memcpy(utv->buffer + (h - i - 1) * w * rgb_size, + pic->data[0] + i * pic->linesize[0], + w * rgb_size); + break; + default: + return AVERROR(EINVAL); + } + + /* Encode frame */ + pkt->size = utv->codec->EncodeFrame(dst, &keyframe, utv->buffer); + + if (!pkt->size) { + av_log(avctx, AV_LOG_ERROR, "EncodeFrame failed!\n"); + return AVERROR_INVALIDDATA; + } + + /* + * Ut Video is intra-only and every frame is a keyframe, + * and the API always returns true. In case something + * durastic changes in the future, such as inter support, + * assert that this is true. + */ + av_assert2(keyframe == true); + avctx->coded_frame->key_frame = 1; + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + return 0; +} + +static av_cold int utvideo_encode_close(AVCodecContext *avctx) +{ + UtVideoContext *utv = (UtVideoContext *)avctx->priv_data; + + av_freep(&avctx->coded_frame); + av_freep(&avctx->extradata); + av_freep(&utv->buffer); + + utv->codec->EncodeEnd(); + CCodec::DeleteInstance(utv->codec); + + return 0; +} + +AVCodec ff_libutvideo_encoder = { + "libutvideo", + NULL_IF_CONFIG_SMALL("Ut Video"), + AVMEDIA_TYPE_VIDEO, + CODEC_ID_UTVIDEO, + CODEC_CAP_AUTO_THREADS | CODEC_CAP_LOSSLESS, + NULL, /* supported_framerates */ + (const enum PixelFormat[]) { + PIX_FMT_YUV420P, PIX_FMT_YUYV422, PIX_FMT_BGR24, + PIX_FMT_RGB32, PIX_FMT_NONE + }, + NULL, /* supported_samplerates */ + NULL, /* sample_fmts */ + NULL, /* channel_layouts */ + 0, /* max_lowres */ + NULL, /* priv_class */ + NULL, /* profiles */ + sizeof(UtVideoContext), + NULL, /* next */ + NULL, /* init_thread_copy */ + NULL, /* update_thread_context */ + NULL, /* defaults */ + NULL, /* init_static_data */ + utvideo_encode_init, + NULL, /* encode */ + utvideo_encode_frame, + NULL, /* decode */ + utvideo_encode_close, + NULL, /* flush */ +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index b8d2bbf2b3..72d5b2e075 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -21,7 +21,7 @@ #define AVCODEC_VERSION_H #define LIBAVCODEC_VERSION_MAJOR 54 -#define LIBAVCODEC_VERSION_MINOR 8 +#define LIBAVCODEC_VERSION_MINOR 9 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ |