diff mbox series

[FFmpeg-devel,7/7] fftools/ffplay: support applying container level cropping

Message ID 20231007162503.1057-8-jamrial@gmail.com
State New
Headers show
Series Container level frame cropping parameters | expand

Commit Message

James Almer Oct. 7, 2023, 4:25 p.m. UTC
Signed-off-by: James Almer <jamrial@gmail.com>
---
 fftools/ffplay.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

Comments

Dmitrii Ovchinnikov Jan. 17, 2024, 6:39 p.m. UTC | #1
I tested these patches with the AMF AV1 encoder(by adding
AV_PKT_DATA_FRAME_CROPPING)
It works fine.

I suggest a small change to the code for better safety. Change this part:
>>if (sd->data && sd->size == sizeof(uint32_t) * 4) {
to:
if (sd && sd->data && sd->size == sizeof(uint32_t) * 4) {

This change helps avoid crashes when the cropping data isn't filled in.
diff mbox series

Patch

diff --git a/fftools/ffplay.c b/fftools/ffplay.c
index d8c69e10bc..5c213bf0d8 100644
--- a/fftools/ffplay.c
+++ b/fftools/ffplay.c
@@ -36,6 +36,7 @@ 
 #include "libavutil/eval.h"
 #include "libavutil/mathematics.h"
 #include "libavutil/pixdesc.h"
+#include "libavutil/intreadwrite.h"
 #include "libavutil/imgutils.h"
 #include "libavutil/dict.h"
 #include "libavutil/fifo.h"
@@ -348,6 +349,7 @@  static const char **vfilters_list = NULL;
 static int nb_vfilters = 0;
 static char *afilters = NULL;
 static int autorotate = 1;
+static int apply_cropping = 1;
 static int find_stream_info = 1;
 static int filter_nbthreads = 0;
 
@@ -1910,6 +1912,28 @@  static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c
     last_filter = filt_ctx;                                                  \
 } while (0)
 
+    if (apply_cropping) {
+        AVPacketSideData *sd = av_packet_side_data_get(is->video_st->codecpar->coded_side_data,
+                                                       is->video_st->codecpar->nb_coded_side_data,
+                                                       AV_PKT_DATA_FRAME_CROPPING);
+
+        if (sd->data && sd->size == sizeof(uint32_t) * 4) {
+            char crop_buf[64];
+            int top    = AV_RL32(sd->data +  0);
+            int bottom = AV_RL32(sd->data +  4);
+            int left   = AV_RL32(sd->data +  8);
+            int right  = AV_RL32(sd->data + 12);
+
+            if (top < 0 || bottom < 0 || left < 0 || right < 0)  {
+                ret = AVERROR(EINVAL);
+                goto fail;
+            }
+
+            snprintf(crop_buf, sizeof(crop_buf), "w=iw-%d-%d:h=ih-%d-%d", left, right, top, bottom);
+            INSERT_FILT("crop", crop_buf);
+        }
+    }
+
     if (autorotate) {
         double theta = 0.0;
         int32_t *displaymatrix = NULL;
@@ -2610,6 +2634,7 @@  static int stream_component_open(VideoState *is, int stream_index)
         av_dict_set(&opts, "threads", "auto", 0);
     if (stream_lowres)
         av_dict_set_int(&opts, "lowres", stream_lowres, 0);
+    av_dict_set_int(&opts, "apply_cropping", apply_cropping, 0);
 
     av_dict_set(&opts, "flags", "+copy_opaque", AV_DICT_MULTIKEY);
 
@@ -3608,6 +3633,7 @@  static const OptionDef options[] = {
     { "scodec", HAS_ARG | OPT_STRING | OPT_EXPERT, { &subtitle_codec_name }, "force subtitle decoder", "decoder_name" },
     { "vcodec", HAS_ARG | OPT_STRING | OPT_EXPERT, {    &video_codec_name }, "force video decoder",    "decoder_name" },
     { "autorotate", OPT_BOOL, { &autorotate }, "automatically rotate video", "" },
+    { "apply_cropping", OPT_BOOL, { &apply_cropping }, "apply frame cropping", "" },
     { "find_stream_info", OPT_BOOL | OPT_INPUT | OPT_EXPERT, { &find_stream_info },
         "read and decode the streams to fill missing information with heuristics" },
     { "filter_threads", HAS_ARG | OPT_INT | OPT_EXPERT, { &filter_nbthreads }, "number of filter threads per graph" },