diff options
Diffstat (limited to 'libavcodec/utvideoenc.c')
-rw-r--r-- | libavcodec/utvideoenc.c | 77 |
1 files changed, 49 insertions, 28 deletions
diff --git a/libavcodec/utvideoenc.c b/libavcodec/utvideoenc.c index ef51ed06dd..840742caf7 100644 --- a/libavcodec/utvideoenc.c +++ b/libavcodec/utvideoenc.c @@ -2,20 +2,20 @@ * Ut Video encoder * Copyright (c) 2012 Jan Ekström * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg 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, + * 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 * 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 + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -33,7 +33,6 @@ #include "bswapdsp.h" #include "bytestream.h" #include "put_bits.h" -#include "huffyuvencdsp.h" #include "mathops.h" #include "utvideo.h" #include "huffman.h" @@ -77,6 +76,7 @@ static av_cold int utvideo_encode_init(AVCodecContext *avctx) c->planes = 4; avctx->codec_tag = MKTAG('U', 'L', 'R', 'A'); original_format = UTVIDEO_RGBA; + avctx->bits_per_coded_sample = 32; break; case AV_PIX_FMT_YUV420P: if (avctx->width & 1 || avctx->height & 1) { @@ -104,6 +104,14 @@ static av_cold int utvideo_encode_init(AVCodecContext *avctx) avctx->codec_tag = MKTAG('U', 'L', 'Y', '2'); original_format = UTVIDEO_422; break; + case AV_PIX_FMT_YUV444P: + c->planes = 3; + if (avctx->colorspace == AVCOL_SPC_BT709) + avctx->codec_tag = MKTAG('U', 'L', 'H', '4'); + else + avctx->codec_tag = MKTAG('U', 'L', 'Y', '4'); + original_format = UTVIDEO_444; + break; default: av_log(avctx, AV_LOG_ERROR, "Unknown pixel format: %d\n", avctx->pix_fmt); @@ -111,7 +119,7 @@ static av_cold int utvideo_encode_init(AVCodecContext *avctx) } ff_bswapdsp_init(&c->bdsp); - ff_huffyuvencdsp_init(&c->hdsp); + ff_llvidencdsp_init(&c->llvidencdsp); #if FF_API_PRIVATE_OPT FF_DISABLE_DEPRECATION_WARNINGS @@ -285,6 +293,9 @@ static void left_predict(uint8_t *src, uint8_t *dst, ptrdiff_t stride, } } +#undef A +#undef B + /* Write data to a plane with median prediction */ static void median_predict(UtvideoContext *c, uint8_t *src, uint8_t *dst, ptrdiff_t stride, int width, int height) @@ -313,7 +324,7 @@ static void median_predict(UtvideoContext *c, uint8_t *src, uint8_t *dst, /* Rest of the coded part uses median prediction */ for (j = 1; j < height; j++) { - c->hdsp.sub_hfyu_median_pred(dst, src - stride, src, width, &A, &B); + c->llvidencdsp.sub_median_pred(dst, src - stride, src, width, &A, &B); dst += width; src += stride; } @@ -388,7 +399,7 @@ static int write_huff_codes(uint8_t *src, uint8_t *dst, int dst_size, } static int encode_plane(AVCodecContext *avctx, uint8_t *src, - uint8_t *dst, ptrdiff_t stride, + uint8_t *dst, ptrdiff_t stride, int plane_no, int width, int height, PutByteContext *pb) { UtvideoContext *c = avctx->priv_data; @@ -398,15 +409,17 @@ static int encode_plane(AVCodecContext *avctx, uint8_t *src, HuffEntry he[256]; uint32_t offset = 0, slice_len = 0; + const int cmask = ~(!plane_no && avctx->pix_fmt == AV_PIX_FMT_YUV420P); int i, sstart, send = 0; int symbol; + int ret; /* Do prediction / make planes */ switch (c->frame_pred) { case PRED_NONE: for (i = 0; i < c->slices; i++) { sstart = send; - send = height * (i + 1) / c->slices; + send = height * (i + 1) / c->slices & cmask; av_image_copy_plane(dst + sstart * width, width, src + sstart * stride, stride, width, send - sstart); @@ -415,7 +428,7 @@ static int encode_plane(AVCodecContext *avctx, uint8_t *src, case PRED_LEFT: for (i = 0; i < c->slices; i++) { sstart = send; - send = height * (i + 1) / c->slices; + send = height * (i + 1) / c->slices & cmask; left_predict(src + sstart * stride, dst + sstart * width, stride, width, send - sstart); } @@ -423,7 +436,7 @@ static int encode_plane(AVCodecContext *avctx, uint8_t *src, case PRED_MEDIAN: for (i = 0; i < c->slices; i++) { sstart = send; - send = height * (i + 1) / c->slices; + send = height * (i + 1) / c->slices & cmask; median_predict(c, src + sstart * stride, dst + sstart * width, stride, width, send - sstart); } @@ -442,7 +455,7 @@ static int encode_plane(AVCodecContext *avctx, uint8_t *src, /* If non-zero count is found, see if it matches width * height */ if (counts[symbol]) { /* Special case if only one symbol was used */ - if (counts[symbol] == width * height) { + if (counts[symbol] == width * (int64_t)height) { /* * Write a zero for the single symbol * used in the plane, else 0xFF. @@ -466,7 +479,8 @@ static int encode_plane(AVCodecContext *avctx, uint8_t *src, } /* Calculate huffman lengths */ - ff_huff_gen_len_table(lengths, counts); + if ((ret = ff_huff_gen_len_table(lengths, counts, 256, 1)) < 0) + return ret; /* * Write the plane's header into the output packet: @@ -486,14 +500,14 @@ static int encode_plane(AVCodecContext *avctx, uint8_t *src, send = 0; for (i = 0; i < c->slices; i++) { sstart = send; - send = height * (i + 1) / c->slices; + send = height * (i + 1) / c->slices & cmask; /* * Write the huffman codes to a buffer, * get the offset in bits and convert to bytes. */ offset += write_huff_codes(dst + sstart * width, c->slice_bits, - width * (send - sstart), width, + width * height + 4, width, send - sstart, he) >> 3; slice_len = offset - slice_len; @@ -540,22 +554,17 @@ static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt, int i, ret = 0; /* Allocate a new packet if needed, and set it to the pointer dst */ - ret = ff_alloc_packet(pkt, (256 + 4 * c->slices + width * height) * - c->planes + 4); + ret = ff_alloc_packet2(avctx, pkt, (256 + 4 * c->slices + width * height) * + c->planes + 4, 0); - if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, - "Error allocating the output packet, or the provided packet " - "was too small.\n"); + if (ret < 0) return ret; - } dst = pkt->data; bytestream2_init_writer(&pb, dst, pkt->size); - av_fast_malloc(&c->slice_bits, &c->slice_bits_size, - width * height + AV_INPUT_BUFFER_PADDING_SIZE); + av_fast_padded_malloc(&c->slice_bits, &c->slice_bits_size, width * height + 4); if (!c->slice_bits) { av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer 2.\n"); @@ -573,7 +582,7 @@ static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt, case AV_PIX_FMT_RGBA: for (i = 0; i < c->planes; i++) { ret = encode_plane(avctx, c->slice_buffer[i] + 2 * c->slice_stride, - c->slice_buffer[i], c->slice_stride, + c->slice_buffer[i], c->slice_stride, i, width, height, &pb); if (ret) { @@ -582,10 +591,21 @@ static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } } break; + case AV_PIX_FMT_YUV444P: + for (i = 0; i < c->planes; i++) { + ret = encode_plane(avctx, pic->data[i], c->slice_buffer[0], + pic->linesize[i], i, width, height, &pb); + + if (ret) { + av_log(avctx, AV_LOG_ERROR, "Error encoding plane %d.\n", i); + return ret; + } + } + break; case AV_PIX_FMT_YUV422P: for (i = 0; i < c->planes; i++) { ret = encode_plane(avctx, pic->data[i], c->slice_buffer[0], - pic->linesize[i], width >> !!i, height, &pb); + pic->linesize[i], i, width >> !!i, height, &pb); if (ret) { av_log(avctx, AV_LOG_ERROR, "Error encoding plane %d.\n", i); @@ -596,7 +616,7 @@ static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt, case AV_PIX_FMT_YUV420P: for (i = 0; i < c->planes; i++) { ret = encode_plane(avctx, pic->data[i], c->slice_buffer[0], - pic->linesize[i], width >> !!i, height >> !!i, + pic->linesize[i], i, width >> !!i, height >> !!i, &pb); if (ret) { @@ -668,8 +688,9 @@ AVCodec ff_utvideo_encoder = { .init = utvideo_encode_init, .encode2 = utvideo_encode_frame, .close = utvideo_encode_close, + .capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_YUV422P, - AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE }, }; |