typedef struct {
const AVClass *av_class;
int log2_count;
+ int hsub, vsub;
int qp;
int qscale_type;
int temp_stride[3];
uint8_t *src[3];
- int16_t *temp[3];
+ uint16_t *temp[3];
int outbuf_size;
uint8_t *outbuf;
AVCodecContext *avctx_enc[BLOCK*BLOCK];
{ 3, 4}, {11, 4}, { 3,12}, {11,12}, { 7, 0}, {15, 0}, { 7, 8}, {15, 8},
};
-static void store_slice_c(uint8_t *dst, const int16_t *src,
+static void store_slice_c(uint8_t *dst, const uint16_t *src,
int dst_stride, int src_stride,
int width, int height, int log2_scale)
{
case FF_QSCALE_TYPE_MPEG2: return qscale >> 1;
case FF_QSCALE_TYPE_H264: return qscale >> 2;
case FF_QSCALE_TYPE_VP56: return (63 - qscale + 2) >> 2;
+ default: av_assert0(0);
}
return qscale;
}
for (i = 0; i < 3; i++) {
int is_chroma = !!i;
- int w = width >> is_chroma;
- int h = height >> is_chroma;
+ int w = width >> (is_chroma ? p->hsub : 0);
+ int h = height >> (is_chroma ? p->vsub : 0);
int stride = p->temp_stride[i];
- int block = BLOCK >> is_chroma;
+ int block = BLOCK >> (is_chroma ? p->hsub : 0);
if (!src[i] || !dst[i])
continue;
if (p->qp)
p->frame->quality = p->qp * FF_QP2LAMBDA;
- else
- p->frame->quality = norm_qscale(qp_store[0], p->qscale_type) * FF_QP2LAMBDA;
+ else {
+ int qpsum=0;
+ int qpcount = (height>>4) * (height>>4);
+
+ for (y = 0; y < (height>>4); y++) {
+ for (x = 0; x < (width>>4); x++)
+ qpsum += qp_store[x + y * qp_stride];
+ }
+ p->frame->quality = norm_qscale((qpsum + qpcount/2) / qpcount, p->qscale_type) * FF_QP2LAMBDA;
+ }
// init per MB qscale stuff FIXME
p->frame->height = height;
p->frame->width = width;
for (i = 0; i < count; i++) {
const int x1 = offset[i+count-1][0];
const int y1 = offset[i+count-1][1];
+ const int x1c = x1 >> p->hsub;
+ const int y1c = y1 >> p->vsub;
+ const int BLOCKc = BLOCK >> p->hsub;
int offset;
AVPacket pkt;
int got_pkt_ptr;
pkt.size = p->outbuf_size;
p->frame->data[0] = p->src[0] + x1 + y1 * p->frame->linesize[0];
- p->frame->data[1] = p->src[1] + x1/2 + y1/2 * p->frame->linesize[1];
- p->frame->data[2] = p->src[2] + x1/2 + y1/2 * p->frame->linesize[2];
+ p->frame->data[1] = p->src[1] + x1c + y1c * p->frame->linesize[1];
+ p->frame->data[2] = p->src[2] + x1c + y1c * p->frame->linesize[2];
p->frame->format = p->avctx_enc[i]->pix_fmt;
avcodec_encode_video2(p->avctx_enc[i], &pkt, p->frame, &got_pkt_ptr);
for (x = 0; x < width; x++)
p->temp[0][x + y * p->temp_stride[0]] += p->frame_dec->data[0][x + y * p->frame_dec->linesize[0] + offset];
- offset = (BLOCK/2-x1/2) + (BLOCK/2-y1/2) * p->frame_dec->linesize[1];
+ if (!src[2] || !dst[2])
+ continue;
+
+ offset = (BLOCKc-x1c) + (BLOCKc-y1c) * p->frame_dec->linesize[1];
- for (y = 0; y < height/2; y++) {
- for (x = 0; x < width/2; x++) {
+ for (y = 0; y < height>>p->vsub; y++) {
+ for (x = 0; x < width>>p->hsub; x++) {
p->temp[1][x + y * p->temp_stride[1]] += p->frame_dec->data[1][x + y * p->frame_dec->linesize[1] + offset];
p->temp[2][x + y * p->temp_stride[2]] += p->frame_dec->data[2][x + y * p->frame_dec->linesize[2] + offset];
}
if (!dst[j])
continue;
store_slice_c(dst[j], p->temp[j], dst_stride[j], p->temp_stride[j],
- width >> is_chroma, height >> is_chroma, 8-p->log2_count);
+ width >> (is_chroma ? p->hsub : 0),
+ height >> (is_chroma ? p->vsub : 0),
+ 8-p->log2_count);
}
}
static int query_formats(AVFilterContext *ctx)
{
static const enum PixelFormat pix_fmts[] = {
- AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P,
- AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV411P,
- AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV440P,
- AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ422P,
- AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ440P,
+ AV_PIX_FMT_YUV444P,
+ AV_PIX_FMT_YUV420P,
+ AV_PIX_FMT_YUV410P,
+ AV_PIX_FMT_YUVJ444P,
+ AV_PIX_FMT_YUVJ420P,
+ AV_PIX_FMT_GRAY8,
AV_PIX_FMT_NONE
};
ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
USPPContext *uspp = ctx->priv;
const int height = inlink->h;
const int width = inlink->w;
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
int i;
AVCodec *enc = avcodec_find_encoder(AV_CODEC_ID_SNOW);
return AVERROR(EINVAL);
}
- if (!uspp->use_bframe_qp) {
- /* we are assuming here the qp blocks will not be smaller that 16x16 */
- uspp->non_b_qp_alloc_size = FF_CEIL_RSHIFT(width, 4) * FF_CEIL_RSHIFT(height, 4);
- uspp->non_b_qp_table = av_calloc(uspp->non_b_qp_alloc_size, sizeof(*uspp->non_b_qp_table));
-
- if (!uspp->non_b_qp_table)
- return AVERROR(ENOMEM);
- }
+ uspp->hsub = desc->log2_chroma_w;
+ uspp->vsub = desc->log2_chroma_h;
for (i = 0; i < 3; i++) {
int is_chroma = !!i;
- int w = ((width + 4 * BLOCK-1) & (~(2 * BLOCK-1))) >> is_chroma;
- int h = ((height + 4 * BLOCK-1) & (~(2 * BLOCK-1))) >> is_chroma;
+ int w = ((width + 4 * BLOCK-1) & (~(2 * BLOCK-1))) >> (is_chroma ? uspp->hsub : 0);
+ int h = ((height + 4 * BLOCK-1) & (~(2 * BLOCK-1))) >> (is_chroma ? uspp->vsub : 0);
uspp->temp_stride[i] = w;
if (!(uspp->temp[i] = av_malloc(uspp->temp_stride[i] * h * sizeof(int16_t))))
avctx_enc->time_base = (AVRational){1,25}; // meaningless
avctx_enc->gop_size = 300;
avctx_enc->max_b_frames = 0;
- avctx_enc->pix_fmt = AV_PIX_FMT_YUV420P;
+ avctx_enc->pix_fmt = inlink->format;
avctx_enc->flags = CODEC_FLAG_QSCALE | CODEC_FLAG_LOW_DELAY;
avctx_enc->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
avctx_enc->global_quality = 123;
w = FF_CEIL_RSHIFT(inlink->w, 4);
h = 1;
} else {
- w = FF_CEIL_RSHIFT(qp_stride, 4);
+ w = qp_stride;
h = FF_CEIL_RSHIFT(inlink->h, 4);
}
+
+ if (w * h > uspp->non_b_qp_alloc_size) {
+ int ret = av_reallocp_array(&uspp->non_b_qp_table, w, h);
+ if (ret < 0) {
+ uspp->non_b_qp_alloc_size = 0;
+ return ret;
+ }
+ uspp->non_b_qp_alloc_size = w * h;
+ }
+
av_assert0(w * h <= uspp->non_b_qp_alloc_size);
memcpy(uspp->non_b_qp_table, qp_table, w * h);
}