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.gil...@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

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to