hevcdec: export cropping information instead of handling it internally
authorAnton Khirnov <anton@khirnov.net>
Sun, 18 Dec 2016 20:11:47 +0000 (21:11 +0100)
committerAnton Khirnov <anton@khirnov.net>
Thu, 12 Jan 2017 15:27:56 +0000 (16:27 +0100)
libavcodec/hevc_parser.c
libavcodec/hevc_ps.c
libavcodec/hevc_ps.h
libavcodec/hevc_refs.c
libavcodec/hevcdec.c
libavcodec/hevcdec.h

index 49e7122..74a0257 100644 (file)
@@ -49,6 +49,7 @@ static int hevc_parse_slice_header(AVCodecParserContext *s, H2645NAL *nal,
 
     HEVCPPS *pps;
     HEVCSPS *sps;
+    HEVCWindow *ow;
     unsigned int pps_id;
 
     get_bits1(gb);          // first slice in pic
@@ -62,12 +63,13 @@ static int hevc_parse_slice_header(AVCodecParserContext *s, H2645NAL *nal,
     }
     pps = (HEVCPPS*)ctx->ps.pps_list[pps_id]->data;
     sps = (HEVCSPS*)ctx->ps.sps_list[pps->sps_id]->data;
+    ow  = &sps->output_window;
 
     /* export the stream parameters */
     s->coded_width  = sps->width;
     s->coded_height = sps->height;
-    s->width        = sps->output_width;
-    s->height       = sps->output_height;
+    s->width        = sps->width  - ow->left_offset - ow->right_offset;
+    s->height       = sps->height - ow->top_offset  - ow->bottom_offset;
     s->format       = sps->pix_fmt;
     avctx->profile  = sps->ptl.general_ptl.profile_idc;
     avctx->level    = sps->ptl.general_ptl.level_idc;
index 2471907..4a5a47e 100644 (file)
@@ -682,6 +682,7 @@ static int map_pixel_format(AVCodecContext *avctx, HEVCSPS *sps)
 int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id,
                       int apply_defdispwin, AVBufferRef **vps_list, AVCodecContext *avctx)
 {
+    HEVCWindow *ow;
     int ret = 0;
     int log2_diff_max_min_transform_block_size;
     int bit_depth_chroma, start, vui_present, sublayer_ordering_info;
@@ -902,32 +903,21 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id,
         sps->output_window.top_offset    += sps->vui.def_disp_win.top_offset;
         sps->output_window.bottom_offset += sps->vui.def_disp_win.bottom_offset;
     }
-    if (sps->output_window.left_offset & (0x1F >> (sps->pixel_shift)) &&
-        !(avctx->flags & AV_CODEC_FLAG_UNALIGNED)) {
-        sps->output_window.left_offset &= ~(0x1F >> (sps->pixel_shift));
-        av_log(avctx, AV_LOG_WARNING, "Reducing left output window to %d "
-               "chroma samples to preserve alignment.\n",
-               sps->output_window.left_offset);
-    }
-    sps->output_width  = sps->width -
-                         (sps->output_window.left_offset + sps->output_window.right_offset);
-    sps->output_height = sps->height -
-                         (sps->output_window.top_offset + sps->output_window.bottom_offset);
-    if (sps->output_width <= 0 || sps->output_height <= 0) {
-        av_log(avctx, AV_LOG_WARNING, "Invalid visible frame dimensions: %dx%d.\n",
-               sps->output_width, sps->output_height);
+
+    ow = &sps->output_window;
+    if (ow->left_offset >= INT_MAX - ow->right_offset     ||
+        ow->top_offset  >= INT_MAX - ow->bottom_offset    ||
+        ow->left_offset + ow->right_offset  >= sps->width ||
+        ow->top_offset  + ow->bottom_offset >= sps->height) {
+        av_log(avctx, AV_LOG_WARNING, "Invalid cropping offsets: %u/%u/%u/%u\n",
+               ow->left_offset, ow->right_offset, ow->top_offset, ow->bottom_offset);
         if (avctx->err_recognition & AV_EF_EXPLODE) {
             ret = AVERROR_INVALIDDATA;
             goto err;
         }
         av_log(avctx, AV_LOG_WARNING,
                "Displaying the whole video surface.\n");
-        sps->output_window.left_offset   =
-        sps->output_window.right_offset  =
-        sps->output_window.top_offset    =
-        sps->output_window.bottom_offset = 0;
-        sps->output_width               = sps->width;
-        sps->output_height              = sps->height;
+        memset(ow, 0, sizeof(*ow));
     }
 
     // Inferred parameters
@@ -1008,7 +998,8 @@ int ff_hevc_decode_nal_sps(GetBitContext *gb, AVCodecContext *avctx,
                "Parsed SPS: id %d; coded wxh: %dx%d; "
                "cropped wxh: %dx%d; pix_fmt: %s.\n",
                sps_id, sps->width, sps->height,
-               sps->output_width, sps->output_height,
+               sps->width - (sps->output_window.left_offset + sps->output_window.right_offset),
+               sps->height - (sps->output_window.top_offset + sps->output_window.bottom_offset),
                av_get_pix_fmt_name(sps->pix_fmt));
     }
 
index d95aa51..89a481b 100644 (file)
@@ -141,8 +141,6 @@ typedef struct HEVCSPS {
     int chroma_format_idc;
     uint8_t separate_colour_plane_flag;
 
-    ///< output (i.e. cropped) values
-    int output_width, output_height;
     HEVCWindow output_window;
 
     HEVCWindow pic_conf_win;
index 30409ba..0c19187 100644 (file)
@@ -162,7 +162,10 @@ int ff_hevc_set_new_ref(HEVCContext *s, AVFrame **frame, int poc)
 
     ref->poc      = poc;
     ref->sequence = s->seq_decode;
-    ref->window   = s->ps.sps->output_window;
+    ref->frame->crop_left   = s->ps.sps->output_window.left_offset;
+    ref->frame->crop_right  = s->ps.sps->output_window.right_offset;
+    ref->frame->crop_top    = s->ps.sps->output_window.top_offset;
+    ref->frame->crop_bottom = s->ps.sps->output_window.bottom_offset;
 
     return 0;
 }
@@ -193,26 +196,12 @@ int ff_hevc_output_frame(HEVCContext *s, AVFrame *out, int flush)
 
         if (nb_output) {
             HEVCFrame *frame = &s->DPB[min_idx];
-            const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->frame->format);
-            int pixel_shift;
-
-            if (!desc)
-                return AVERROR_BUG;
-
-            pixel_shift = desc->comp[0].depth > 8;
 
             ret = av_frame_ref(out, frame->frame);
             ff_hevc_unref_frame(s, frame, HEVC_FRAME_FLAG_OUTPUT);
             if (ret < 0)
                 return ret;
 
-            for (i = 0; i < 3; i++) {
-                int hshift = (i > 0) ? desc->log2_chroma_w : 0;
-                int vshift = (i > 0) ? desc->log2_chroma_h : 0;
-                int off = ((frame->window.left_offset >> hshift) << pixel_shift) +
-                          (frame->window.top_offset   >> vshift) * out->linesize[i];
-                out->data[i] += off;
-            }
             av_log(s->avctx, AV_LOG_DEBUG,
                    "Output frame with POC %d.\n", frame->poc);
             return 1;
index 700b5f0..a4c936e 100644 (file)
@@ -338,13 +338,14 @@ static void export_stream_params(AVCodecContext *avctx, const HEVCParamSets *ps,
                                  const HEVCSPS *sps)
 {
     const HEVCVPS *vps = (const HEVCVPS*)ps->vps_list[sps->vps_id]->data;
+    const HEVCWindow *ow = &sps->output_window;
     unsigned int num = 0, den = 0;
 
     avctx->pix_fmt             = sps->pix_fmt;
     avctx->coded_width         = sps->width;
     avctx->coded_height        = sps->height;
-    avctx->width               = sps->output_width;
-    avctx->height              = sps->output_height;
+    avctx->width               = sps->width  - ow->left_offset - ow->right_offset;
+    avctx->height              = sps->height - ow->top_offset  - ow->bottom_offset;
     avctx->has_b_frames        = sps->temporal_layer[sps->max_sub_layers - 1].num_reorder_pics;
     avctx->profile             = sps->ptl.general_ptl.profile_idc;
     avctx->level               = sps->ptl.general_ptl.level_idc;
@@ -2864,7 +2865,6 @@ static int hevc_ref_frame(HEVCContext *s, HEVCFrame *dst, HEVCFrame *src)
 
     dst->poc        = src->poc;
     dst->ctb_count  = src->ctb_count;
-    dst->window     = src->window;
     dst->flags      = src->flags;
     dst->sequence   = src->sequence;
 
@@ -3092,4 +3092,5 @@ AVCodec ff_hevc_decoder = {
     .capabilities          = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
                              AV_CODEC_CAP_FRAME_THREADS,
     .profiles              = NULL_IF_CONFIG_SMALL(ff_hevc_profiles),
+    .caps_internal         = FF_CODEC_CAP_EXPORTS_CROPPING,
 };
index 82adad2..ff192f6 100644 (file)
@@ -374,8 +374,6 @@ typedef struct HEVCFrame {
     int poc;
     struct HEVCFrame *collocated_ref;
 
-    HEVCWindow window;
-
     AVBufferRef *tab_mvf_buf;
     AVBufferRef *rpl_tab_buf;
     AVBufferRef *rpl_buf;