[FFmpeg-devel] [PATCH 6/6] h264_changesps_bsf: allow specifying full cropping
Christophe Gisquet
christophe.gisquet at gmail.com
Sun Nov 30 01:45:56 CET 2014
The decoder support is unfortunately dismal.
---
libavcodec/h264_changesps_bsf.c | 103 +++++++++++++++++++++++++---------------
1 file changed, 64 insertions(+), 39 deletions(-)
diff --git a/libavcodec/h264_changesps_bsf.c b/libavcodec/h264_changesps_bsf.c
index 43e0d62..39896fa 100644
--- a/libavcodec/h264_changesps_bsf.c
+++ b/libavcodec/h264_changesps_bsf.c
@@ -1,6 +1,7 @@
/*
* H.264 change sps filter
* Copyright (c) 2010 Zongyi Zhou <zhouzy at os.pku.edu.cn>
+ * Copyright (c) 2014 Christophe Gisquet <christophe.gisquet at gmail.com>
*
* This file is part of FFmpeg.
*
@@ -35,15 +36,16 @@ typedef struct H264SPSContext {
int32_t refs;
uint32_t remove_nal_flags, delay_remove_flags;
int16_t sar_x, sar_y;
- int16_t crop_x, crop_y;
+ int16_t crop[4];
int8_t fullrange, colorprim, transfer, colmatrix;
} H264SPSContext;
static int parse_args(struct H264SPSContext *c, const char *args)
{
int r = 0;
- int32_t sarx = -1, sary = -1, cropx = -1, cropy = -1, level = -1,
+ int32_t sarx = -1, sary = -1, level = -1,
refs = -1, colorprim = -1, transfer = -1, colmatrix = -1;
+ int32_t cropl = -1, cropt = -1, cropr = -1, cropb = -1;
if (!args) return 0;
c->fps_den = c->fps_num = c->fps_mode = -1;
c->fullrange = -1;
@@ -51,13 +53,15 @@ static int parse_args(struct H264SPSContext *c, const char *args)
while (*args) {
if (sscanf(args, "fps=%u:%u", &c->fps_num, &c->fps_den) == 2 ||
sscanf(args, "sar=%u:%u", &sarx, &sary) == 2 ||
- sscanf(args, "crop=%u:%u", &cropx, &cropy) == 2 ||
sscanf(args, "level=%u", &level) == 1 ||
sscanf(args, "ref=%u", &refs) == 1 ||
sscanf(args, "colorprim=%u", &colorprim) == 1 ||
sscanf(args, "transfer=%u", &transfer) == 1 ||
sscanf(args, "colormatrix=%u", &colmatrix) == 1)
r++;
+ else if (sscanf(args, "crop=%u:%u:%u:%u",
+ &cropl, &cropt, &cropr, &cropb) == 4)
+ r++;
else if (!strncmp(args, "vfr", 3)) {
r++;
c->fps_mode = 0;
@@ -84,9 +88,11 @@ static int parse_args(struct H264SPSContext *c, const char *args)
args++;
}
if (sary == -1) sarx = -1;
- if (cropy == -1) cropx = -1;
+ if (cropt == -1) cropl = -1;
+ if (cropb == -1) cropr = -1;
c->sar_x = sarx; c->sar_y = sary;
- c->crop_x = cropx; c->crop_y = cropy;
+ c->crop[0] = cropl; c->crop[1] = cropr;
+ c->crop[2] = cropt; c->crop[3] = cropb;
c->level = level;
c->refs = refs;
c->colorprim = colorprim;
@@ -172,7 +178,9 @@ static int h264_modify(uint8_t *outbuf, const uint8_t *inbuf, H264SPSContext *ct
#define COPYUE31 set_ue_golomb(&pb, get_ue_golomb_31(&gb))
#define COPYSE set_se_golomb(&pb, get_se_golomb(&gb))
#define COPYBITS1 put_bits(&pb, 1, get_bits1(&gb))
- int p, t, i;
+ int p, t, i, frame_mbs_only, mb_width, mb_height;
+ int chroma_format_idc = 1; // default value for non-High profile
+ int csub[2];
init_get_bits(&gb, inbuf, insize * 8);
init_put_bits(&pb, outbuf, (insize + 10) * 8);
p = get_bits(&gb, 8); //profile_idc
@@ -184,9 +192,9 @@ static int h264_modify(uint8_t *outbuf, const uint8_t *inbuf, H264SPSContext *ct
put_bits(&pb, 8, t);
COPYUE31;
if (p >= 100) {
- t = get_ue_golomb(&gb); //chroma_format_idc
- set_ue_golomb(&pb, t);
- if (t == 3)
+ chroma_format_idc = get_ue_golomb(&gb);
+ set_ue_golomb(&pb, chroma_format_idc);
+ if (chroma_format_idc == 3)
COPYBITS1; //residue_transform_flag
COPYUE; //bit_depth_luma_minus8
COPYUE; //bit_depth_chroma_minus8
@@ -221,38 +229,49 @@ static int h264_modify(uint8_t *outbuf, const uint8_t *inbuf, H264SPSContext *ct
t = ctx->refs;
set_ue_golomb(&pb,t);
COPYBITS1;
- COPYUE;
- COPYUE;
- i = get_bits1(&gb); //frame_mbs_only
- put_bits(&pb, 1, i);
- if (!i) COPYBITS1;
+ mb_width = get_ue_golomb(&gb);
+ mb_height = get_ue_golomb(&gb);
+ set_ue_golomb(&pb,mb_width);
+ set_ue_golomb(&pb,mb_height);
+ frame_mbs_only = get_bits1(&gb);
+ put_bits(&pb, 1, frame_mbs_only);
+ if (!frame_mbs_only) COPYBITS1;
COPYBITS1;
+ csub[0] = (chroma_format_idc == 1 || chroma_format_idc == 2) ? 1 : 0;
+ csub[1] = (chroma_format_idc == 1) ? 1 : 0;
+ csub[1] += 1-frame_mbs_only;
t = get_bits1(&gb);
- if (ctx->crop_x == -1)
- put_bits(&pb, 1, t);
if (t) {
- int t1, t2, t3, t4;
- t1 = get_ue_golomb(&gb),
- t2 = get_ue_golomb(&gb),
- t3 = get_ue_golomb(&gb),
- t4 = get_ue_golomb(&gb);
- if (ctx->crop_x == -1) {
- set_ue_golomb(&pb, t1);
- set_ue_golomb(&pb, t2);
- set_ue_golomb(&pb, t3);
- set_ue_golomb(&pb, t4);
+ for (i=0; i<4; i++) {
+ int val = get_ue_golomb(&gb);
+ if (ctx->crop[i] < 0)
+ ctx->crop[i] = val << csub[i>>1];
}
}
- if (ctx->crop_x != -1) {
- if (ctx->crop_x || ctx->crop_y) {
- put_bits(&pb, 1, 1);
- set_ue_golomb(&pb, 0);
- set_ue_golomb(&pb, (ctx->crop_x + 1) >> 1);
- set_ue_golomb(&pb, 0);
- set_ue_golomb(&pb, (ctx->crop_y + 1) >> (2 >> i));
- } else put_bits(&pb, 1, 0);
- }
+ if (ctx->crop[0] >= 0 || ctx->crop[1] >= 0 ||
+ ctx->crop[2] >= 0 || ctx->crop[3] >= 0) {
+ static const char* names[4] = { "left", "right", "top", "bottom" };
+ int dim[2] = { 16 * mb_width, 16 * mb_height * (2 - frame_mbs_only) };
+
+ put_bits(&pb, 1, 1);
+
+ for (i=0; i<4; i++) {
+ int s = csub[i>>1], d = dim[i>>1];
+ int crop = ctx->crop[i] < 0 ? 0 : (ctx->crop[i] & -1L <<s);
+ if (crop >= d || (i&1 && crop+ctx->crop[i-1] >= d)) {
+ av_log(ctx, AV_LOG_WARNING, "Invalid %s crop value %d / %d\n",
+ names[i], ctx->crop[i], d);
+ crop = 0;
+ } else if (crop != ctx->crop[i])
+ av_log(ctx, AV_LOG_WARNING, "Changed %s crop from %d to %d\n",
+ names[i], ctx->crop[i], crop);
+ set_ue_golomb(&pb, crop>>s);
+ ctx->crop[i] = crop;
+ }
+ } else
+ put_bits(&pb, 1, 0);
+
t = get_bits1(&gb);
put_bits(&pb, 1, t);
if (t) {
@@ -470,10 +489,16 @@ static int h264_changesps_filter(AVBitStreamFilterContext *bsfc,
ndata[3] = ctx->level;
m = (ndata[5] & 0x1f)? 6 : 7;
AV_WB16(ndata + m, AV_RB16(ndata + m) + d);
- if (ctx->crop_x != -1) {
- avctx->width = ((avctx->width + 15) & ~15) - ctx->crop_x;
- avctx->height = ((avctx->height + 15) & ~15) - ctx->crop_y;
- }
+ d = ctx->crop[0] < 0 ? 0 : ctx->crop[0];
+ if (ctx->crop[1] > 0)
+ d += ctx->crop[1];
+ if (d > 0)
+ avctx->width = ((avctx->width + 15) & ~15) - d;
+ d = ctx->crop[2] < 0 ? 0 : ctx->crop[2];
+ if (ctx->crop[3] > 0)
+ d += ctx->crop[3];
+ if (d > 0)
+ avctx->height = ((avctx->height + 15) & ~15) - d;
r = ctx->fps_num;
if (r > 0) {
avctx->time_base.den = r;
--
1.9.2.msysgit.0
More information about the ffmpeg-devel
mailing list