X-Git-Url: https://git.piment-noir.org/?p=deb_ffmpeg.git;a=blobdiff_plain;f=ffmpeg%2Flibavcodec%2Fv210enc.c;h=0d40f9999386bcadba4ef17c90a7e91cec45eb22;hp=1e53bdbdda4bef63a83d073f7dc75b2c85378716;hb=f6fa7814ccfe3e76514b36cf04f5cd3cb657c8cf;hpb=2ba45a602cbfa7b771effba9b11bb4245c21bc00 diff --git a/ffmpeg/libavcodec/v210enc.c b/ffmpeg/libavcodec/v210enc.c index 1e53bdb..0d40f99 100644 --- a/ffmpeg/libavcodec/v210enc.c +++ b/ffmpeg/libavcodec/v210enc.c @@ -24,82 +24,190 @@ #include "avcodec.h" #include "bytestream.h" #include "internal.h" +#include "v210enc.h" + +#define CLIP(v) av_clip(v, 4, 1019) +#define CLIP8(v) av_clip(v, 1, 254) + +#define WRITE_PIXELS(a, b, c) \ + do { \ + val = CLIP(*a++); \ + val |= (CLIP(*b++) << 10) | \ + (CLIP(*c++) << 20); \ + AV_WL32(dst, val); \ + dst += 4; \ + } while (0) + +#define WRITE_PIXELS8(a, b, c) \ + do { \ + val = (CLIP8(*a++) << 2); \ + val |= (CLIP8(*b++) << 12) | \ + (CLIP8(*c++) << 22); \ + AV_WL32(dst, val); \ + dst += 4; \ + } while (0) + +static void v210_planar_pack_8_c(const uint8_t *y, const uint8_t *u, + const uint8_t *v, uint8_t *dst, ptrdiff_t width) +{ + uint32_t val; + int i; + + /* unroll this to match the assembly */ + for( i = 0; i < width-11; i += 12 ){ + WRITE_PIXELS8(u, y, v); + WRITE_PIXELS8(y, u, y); + WRITE_PIXELS8(v, y, u); + WRITE_PIXELS8(y, v, y); + WRITE_PIXELS8(u, y, v); + WRITE_PIXELS8(y, u, y); + WRITE_PIXELS8(v, y, u); + WRITE_PIXELS8(y, v, y); + } +} + +static void v210_planar_pack_10_c(const uint16_t *y, const uint16_t *u, + const uint16_t *v, uint8_t *dst, ptrdiff_t width) +{ + uint32_t val; + int i; + + for( i = 0; i < width-5; i += 6 ){ + WRITE_PIXELS(u, y, v); + WRITE_PIXELS(y, u, y); + WRITE_PIXELS(v, y, u); + WRITE_PIXELS(y, v, y); + } +} static av_cold int encode_init(AVCodecContext *avctx) { + V210EncContext *s = avctx->priv_data; + if (avctx->width & 1) { av_log(avctx, AV_LOG_ERROR, "v210 needs even width\n"); return AVERROR(EINVAL); } - if (avctx->bits_per_raw_sample != 10) - av_log(avctx, AV_LOG_WARNING, "bits per raw sample: %d != 10-bit\n", - avctx->bits_per_raw_sample); - avctx->coded_frame = av_frame_alloc(); if (!avctx->coded_frame) return AVERROR(ENOMEM); avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + s->pack_line_8 = v210_planar_pack_8_c; + s->pack_line_10 = v210_planar_pack_10_c; + + if (ARCH_X86) + ff_v210enc_init_x86(s); + return 0; } static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pic, int *got_packet) { + V210EncContext *s = avctx->priv_data; + int aligned_width = ((avctx->width + 47) / 48) * 48; int stride = aligned_width * 8 / 3; int line_padding = stride - ((avctx->width * 8 + 11) / 12) * 4; int h, w, ret; - const uint16_t *y = (const uint16_t*)pic->data[0]; - const uint16_t *u = (const uint16_t*)pic->data[1]; - const uint16_t *v = (const uint16_t*)pic->data[2]; - PutByteContext p; + uint8_t *dst; - if ((ret = ff_alloc_packet2(avctx, pkt, avctx->height * stride)) < 0) + if ((ret = ff_alloc_packet(pkt, avctx->height * stride)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); return ret; + } - bytestream2_init_writer(&p, pkt->data, pkt->size); + dst = pkt->data; + + if (pic->format == AV_PIX_FMT_YUV422P10) { + const uint16_t *y = (const uint16_t*)pic->data[0]; + const uint16_t *u = (const uint16_t*)pic->data[1]; + const uint16_t *v = (const uint16_t*)pic->data[2]; + for (h = 0; h < avctx->height; h++) { + uint32_t val; + w = (avctx->width / 6) * 6; + s->pack_line_10(y, u, v, dst, w); + + y += w; + u += w >> 1; + v += w >> 1; + dst += (w / 6) * 16; + if (w < avctx->width - 1) { + WRITE_PIXELS(u, y, v); + + val = CLIP(*y++); + if (w == avctx->width - 2) { + AV_WL32(dst, val); + dst += 4; + } + } + if (w < avctx->width - 3) { + val |= (CLIP(*u++) << 10) | (CLIP(*y++) << 20); + AV_WL32(dst, val); + dst += 4; -#define CLIP(v) av_clip(v, 4, 1019) + val = CLIP(*v++) | (CLIP(*y++) << 10); + AV_WL32(dst, val); + dst += 4; + } -#define WRITE_PIXELS(a, b, c) \ - do { \ - val = CLIP(*a++); \ - val |= (CLIP(*b++) << 10) | \ - (CLIP(*c++) << 20); \ - bytestream2_put_le32u(&p, val); \ - } while (0) + memset(dst, 0, line_padding); + dst += line_padding; - for (h = 0; h < avctx->height; h++) { - uint32_t val; - for (w = 0; w < avctx->width - 5; w += 6) { - WRITE_PIXELS(u, y, v); - WRITE_PIXELS(y, u, y); - WRITE_PIXELS(v, y, u); - WRITE_PIXELS(y, v, y); + y += pic->linesize[0] / 2 - avctx->width; + u += pic->linesize[1] / 2 - avctx->width / 2; + v += pic->linesize[2] / 2 - avctx->width / 2; } - if (w < avctx->width - 1) { - WRITE_PIXELS(u, y, v); - - val = CLIP(*y++); - if (w == avctx->width - 2) - bytestream2_put_le32u(&p, val); + } + else if(pic->format == AV_PIX_FMT_YUV422P) { + const uint8_t *y = pic->data[0]; + const uint8_t *u = pic->data[1]; + const uint8_t *v = pic->data[2]; + for (h = 0; h < avctx->height; h++) { + uint32_t val; + w = (avctx->width / 12) * 12; + s->pack_line_8(y, u, v, dst, w); + + y += w; + u += w >> 1; + v += w >> 1; + dst += (w / 12) * 32; + + for( ; w < avctx->width-5; w += 6 ){ + WRITE_PIXELS8(u, y, v); + WRITE_PIXELS8(y, u, y); + WRITE_PIXELS8(v, y, u); + WRITE_PIXELS8(y, v, y); + } + if (w < avctx->width - 1) { + WRITE_PIXELS8(u, y, v); + + val = CLIP8(*y++) << 2; + if (w == avctx->width - 2) { + AV_WL32(dst, val); + dst += 4; + } + } if (w < avctx->width - 3) { - val |= (CLIP(*u++) << 10) | (CLIP(*y++) << 20); - bytestream2_put_le32u(&p, val); + val |= (CLIP8(*u++) << 12) | (CLIP8(*y++) << 22); + AV_WL32(dst, val); + dst += 4; - val = CLIP(*v++) | (CLIP(*y++) << 10); - bytestream2_put_le32u(&p, val); + val = (CLIP8(*v++) << 2) | (CLIP8(*y++) << 12); + AV_WL32(dst, val); + dst += 4; } - } - bytestream2_set_buffer(&p, 0, line_padding); + memset(dst, 0, line_padding); + dst += line_padding; - y += pic->linesize[0] / 2 - avctx->width; - u += pic->linesize[1] / 2 - avctx->width / 2; - v += pic->linesize[2] / 2 - avctx->width / 2; + y += pic->linesize[0] - avctx->width; + u += pic->linesize[1] - avctx->width / 2; + v += pic->linesize[2] - avctx->width / 2; + } } pkt->flags |= AV_PKT_FLAG_KEY; @@ -119,8 +227,9 @@ AVCodec ff_v210_encoder = { .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_V210, + .priv_data_size = sizeof(V210EncContext), .init = encode_init, .encode2 = encode_frame, .close = encode_close, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P10, AV_PIX_FMT_NONE }, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE }, };