[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