[FFmpeg-devel] [PATCH] avdevice/decklink: new options 'list_pixelformats' and 'pixelformat_code' to allow pixelformat selection by code

Gildas Fargeas fargeas.gildas at gmail.com
Fri Sep 1 18:42:39 EEST 2017


I removed the option bm_v210 as it is replaced with a more complete pixel format selection option.
The main objective for this patch was to enable RGB capture.
The pixel format codes are directly copied from the Decklink API.

Signed-off-by: Gildas Fargeas <fargeas.gildas at gmail.com>
---
 libavdevice/decklink_common.cpp | 34 ++++++++++++++++++++++++--
 libavdevice/decklink_common.h   | 17 +++++++++++++
 libavdevice/decklink_common_c.h |  3 ++-
 libavdevice/decklink_dec.cpp    | 53 ++++++++++++++++++++++++++++++++++-------
 libavdevice/decklink_dec_c.c    |  3 ++-
 5 files changed, 98 insertions(+), 12 deletions(-)

diff --git a/libavdevice/decklink_common.cpp b/libavdevice/decklink_common.cpp
index cbb591ce64..6c3d2cc2c1 100644
--- a/libavdevice/decklink_common.cpp
+++ b/libavdevice/decklink_common.cpp
@@ -203,6 +203,18 @@ int ff_decklink_set_format(AVFormatContext *avctx,
     if (cctx->format_code)
         memcpy(format_buf, cctx->format_code, FFMIN(strlen(cctx->format_code), sizeof(format_buf)));
     BMDDisplayMode target_mode = (BMDDisplayMode)AV_RB32(format_buf);
+
+    char pixel_buf[] = "    ";
+    ctx->bmd_pixel= bmdFormat8BitYUV;
+    if (cctx->pixel_code) {
+        if (!strcmp(cctx->pixel_code, "ARGB")) {
+            ctx->bmd_pixel = bmdFormat8BitARGB;
+        } else {
+            memcpy(pixel_buf, cctx->pixel_code, FFMIN(strlen(cctx->pixel_code), sizeof(pixel_buf)));
+            ctx->bmd_pixel = (BMDPixelFormat)AV_RB32(pixel_buf);
+        }
+    }
+
     AVRational target_tb = av_make_q(tb_num, tb_den);
     ctx->bmd_mode = bmdModeUnknown;
     while ((ctx->bmd_mode == bmdModeUnknown) && itermode->Next(&mode) == S_OK) {
@@ -241,12 +253,12 @@ int ff_decklink_set_format(AVFormatContext *avctx,
     if (ctx->bmd_mode == bmdModeUnknown)
         return -1;
     if (direction == DIRECTION_IN) {
-        if (ctx->dli->DoesSupportVideoMode(ctx->bmd_mode, bmdFormat8BitYUV,
+        if (ctx->dli->DoesSupportVideoMode(ctx->bmd_mode, ctx->bmd_pixel,
                                            bmdVideoOutputFlagDefault,
                                            &support, NULL) != S_OK)
             return -1;
     } else {
-        if (ctx->dlo->DoesSupportVideoMode(ctx->bmd_mode, bmdFormat8BitYUV,
+        if (ctx->dlo->DoesSupportVideoMode(ctx->bmd_mode, ctx->bmd_pixel,
                                            bmdVideoOutputFlagDefault,
                                            &support, NULL) != S_OK)
         return -1;
@@ -332,6 +344,24 @@ int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direct
     return 0;
 }
 
+
+int ff_decklink_list_pixelformats(AVFormatContext *avctx)
+{
+	unsigned i = 0;
+
+
+    av_log(avctx, AV_LOG_INFO, "List of pixel formats for '%s':\n\tformat_code",
+               avctx->filename);
+    for (i=0; i < sizeof(decklink_pixelformat)/sizeof(char*);i++) {
+        av_log(avctx, AV_LOG_INFO, "\n\t%.4s",
+                decklink_pixelformat[i]);
+    }
+    av_log(avctx, AV_LOG_INFO, "\n");
+
+    return 0;
+}
+
+
 void ff_decklink_cleanup(AVFormatContext *avctx)
 {
     struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data;
diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h
index 749eb0f8b8..964781ff72 100644
--- a/libavdevice/decklink_common.h
+++ b/libavdevice/decklink_common.h
@@ -56,6 +56,7 @@ struct decklink_ctx {
     BMDTimeValue bmd_tb_den;
     BMDTimeValue bmd_tb_num;
     BMDDisplayMode bmd_mode;
+    BMDPixelFormat bmd_pixel;
     BMDVideoConnection video_input;
     BMDAudioConnection audio_input;
     int bmd_width;
@@ -82,6 +83,7 @@ struct decklink_ctx {
     /* Options */
     int list_devices;
     int list_formats;
+    int list_pixelformats;
     int64_t teletext_lines;
     double preroll;
     int duplex_mode;
@@ -132,11 +134,26 @@ static const BMDVideoConnection decklink_video_connection_map[] = {
     bmdVideoConnectionSVideo,
 };
 
+static const char * const decklink_pixelformat[] = {
+	"2vuy",     /* bmdFormat8BitYUV     */
+	"v210",     /* bmdFormat10BitYUV    */
+	"ARGB",     /* bmdFormat8BitARGB    */
+	"BGRA",     /* bmdFormat8BitBGRA    */
+	"r210",     /* bmdFormat10BitRGB    */
+	"R12B",     /* bmdFormat12BitRGB    */
+	"R12L",     /* bmdFormat12BitRGBLE  */
+	"R10l",     /* bmdFormat10BitRGBXLE */
+	"R10b",     /* bmdFormat10BitRGBX   */
+	"hev1",     /* bmdFormatH265        */
+	"AVdh"      /* bmdFormatDNxHR       */
+};
+
 HRESULT ff_decklink_get_display_name(IDeckLink *This, const char **displayName);
 int ff_decklink_set_format(AVFormatContext *avctx, int width, int height, int tb_num, int tb_den, enum AVFieldOrder field_order, decklink_direction_t direction = DIRECTION_OUT, int num = 0);
 int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t direction, int num);
 int ff_decklink_list_devices(AVFormatContext *avctx);
 int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direction = DIRECTION_OUT);
+int ff_decklink_list_pixelformats(AVFormatContext *avctx);
 void ff_decklink_cleanup(AVFormatContext *avctx);
 int ff_decklink_init_device(AVFormatContext *avctx, const char* name);
 
diff --git a/libavdevice/decklink_common_c.h b/libavdevice/decklink_common_c.h
index e263480474..d2f993310f 100644
--- a/libavdevice/decklink_common_c.h
+++ b/libavdevice/decklink_common_c.h
@@ -38,9 +38,9 @@ struct decklink_cctx {
     /* Options */
     int list_devices;
     int list_formats;
+    int list_pixelformats;
     int64_t teletext_lines;
     double preroll;
-    int v210;
     int audio_channels;
     int duplex_mode;
     DecklinkPtsSource audio_pts_source;
@@ -49,6 +49,7 @@ struct decklink_cctx {
     int video_input;
     int draw_bars;
     char *format_code;
+    char *pixel_code;
     int64_t queue_size;
 };
 
diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
index c271ff3639..c9418828ee 100644
--- a/libavdevice/decklink_dec.cpp
+++ b/libavdevice/decklink_dec.cpp
@@ -622,6 +622,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
         return AVERROR(ENOMEM);
     ctx->list_devices = cctx->list_devices;
     ctx->list_formats = cctx->list_formats;
+    ctx->list_pixelformats = cctx->list_pixelformats;
     ctx->teletext_lines = cctx->teletext_lines;
     ctx->preroll      = cctx->preroll;
     ctx->duplex_mode  = cctx->duplex_mode;
@@ -677,11 +678,17 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
         ret = AVERROR_EXIT;
         goto error;
     }
+    /* List supported pixel formats. */
+    if (ctx->list_pixelformats) {
+        ff_decklink_list_pixelformats(avctx);
+        ret = AVERROR_EXIT;
+        goto error;
+    }
 
     if (mode_num > 0 || cctx->format_code) {
         if (ff_decklink_set_format(avctx, DIRECTION_IN, mode_num) < 0) {
-            av_log(avctx, AV_LOG_ERROR, "Could not set mode number %d or format code %s for %s\n",
-                mode_num, (cctx->format_code) ? cctx->format_code : "(unset)", fname);
+            av_log(avctx, AV_LOG_ERROR, "Could not set mode number %d, format code %s or pixel format %s for %s\n",
+                mode_num, (cctx->format_code) ? cctx->format_code : "(unset)", (cctx->pixel_code) ? cctx->pixel_code : "(unset)", fname);
             ret = AVERROR(EIO);
             goto error;
         }
@@ -723,15 +730,45 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
     st->time_base.num      = ctx->bmd_tb_num;
     av_stream_set_r_frame_rate(st, av_make_q(st->time_base.den, st->time_base.num));
 
-    if (cctx->v210) {
+    switch(ctx->bmd_pixel) {
+    case bmdFormat8BitYUV:
+        st->codecpar->codec_id    = AV_CODEC_ID_RAWVIDEO;
+        st->codecpar->format      = AV_PIX_FMT_UYVY422;
+        st->codecpar->bit_rate    = av_rescale(ctx->bmd_width * ctx->bmd_height * 16, st->time_base.den, st->time_base.num);
+        break;
+    case bmdFormat10BitYUV:
         st->codecpar->codec_id    = AV_CODEC_ID_V210;
         st->codecpar->codec_tag   = MKTAG('V', '2', '1', '0');
+        st->codecpar->bits_per_coded_sample = 10;
         st->codecpar->bit_rate    = av_rescale(ctx->bmd_width * ctx->bmd_height * 64, st->time_base.den, st->time_base.num * 3);
-    } else {
+
+        break;
+    case bmdFormat8BitARGB:
         st->codecpar->codec_id    = AV_CODEC_ID_RAWVIDEO;
-        st->codecpar->format      = AV_PIX_FMT_UYVY422;
-        st->codecpar->codec_tag   = MKTAG('U', 'Y', 'V', 'Y');
-        st->codecpar->bit_rate    = av_rescale(ctx->bmd_width * ctx->bmd_height * 16, st->time_base.den, st->time_base.num);
+        st->codecpar->codec_tag   = avcodec_pix_fmt_to_codec_tag((enum AVPixelFormat)st->codecpar->format);
+        st->codecpar->format    = AV_PIX_FMT_ARGB;
+        break;
+    case bmdFormat8BitBGRA:
+        st->codecpar->codec_id    = AV_CODEC_ID_RAWVIDEO;
+        st->codecpar->codec_tag   = avcodec_pix_fmt_to_codec_tag((enum AVPixelFormat)st->codecpar->format);
+        st->codecpar->format    = AV_PIX_FMT_BGRA;
+        break;
+    case bmdFormat10BitRGB:
+        st->codecpar->codec_id    = AV_CODEC_ID_R210;
+        st->codecpar->format    = AV_PIX_FMT_RGB48LE;
+        st->codecpar->codec_tag   = MKTAG('R', '2', '1', '0');
+        st->codecpar->bits_per_coded_sample = 10;
+        break;
+    case bmdFormat12BitRGB:
+    case bmdFormat12BitRGBLE:
+    case bmdFormat10BitRGBXLE:
+    case bmdFormat10BitRGBX:
+    case bmdFormatH265:
+    case bmdFormatDNxHR:
+    default:
+        av_log(avctx, AV_LOG_ERROR, "Pixel Format %s not supported\n", cctx->pixel_code);
+        ret = AVERROR(ENOMEM);
+        goto error;
     }
 
     switch (ctx->bmd_field_dominance) {
@@ -776,7 +813,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
     }
 
     result = ctx->dli->EnableVideoInput(ctx->bmd_mode,
-                                        cctx->v210 ? bmdFormat10BitYUV : bmdFormat8BitYUV,
+                                        ctx->bmd_pixel,
                                         bmdVideoInputFlagDefault);
 
     if (result != S_OK) {
diff --git a/libavdevice/decklink_dec_c.c b/libavdevice/decklink_dec_c.c
index e2118a619c..9b53d95e96 100644
--- a/libavdevice/decklink_dec_c.c
+++ b/libavdevice/decklink_dec_c.c
@@ -32,8 +32,9 @@
 static const AVOption options[] = {
     { "list_devices", "list available devices"  , OFFSET(list_devices), AV_OPT_TYPE_INT   , { .i64 = 0   }, 0, 1, DEC },
     { "list_formats", "list supported formats"  , OFFSET(list_formats), AV_OPT_TYPE_INT   , { .i64 = 0   }, 0, 1, DEC },
+    { "list_pixelformats", "list supported pixel formats"  , OFFSET(list_pixelformats), AV_OPT_TYPE_INT   , { .i64 = 0   }, 0, 1, DEC },
     { "format_code",  "set format by fourcc"    , OFFSET(format_code),  AV_OPT_TYPE_STRING, { .str = NULL}, 0, 0, DEC },
-    { "bm_v210",      "v210 10 bit per channel" , OFFSET(v210),         AV_OPT_TYPE_INT   , { .i64 = 0   }, 0, 1, DEC },
+    { "pixelformat_code",  "set pixel format according" , OFFSET(pixel_code),  AV_OPT_TYPE_STRING, { .str = NULL}, 0, 0, DEC },
     { "teletext_lines", "teletext lines bitmask", OFFSET(teletext_lines), AV_OPT_TYPE_INT64, { .i64 = 0   }, 0, 0x7ffffffffLL, DEC, "teletext_lines"},
     { "standard",     NULL,                                           0,  AV_OPT_TYPE_CONST, { .i64 = 0x7fff9fffeLL}, 0, 0,    DEC, "teletext_lines"},
     { "all",          NULL,                                           0,  AV_OPT_TYPE_CONST, { .i64 = 0x7ffffffffLL}, 0, 0,    DEC, "teletext_lines"},
-- 
2.11.0



More information about the ffmpeg-devel mailing list