Ticket #9271: 0001-avdevice-dshow-discover-source-color-range-space-etc.patch

File 0001-avdevice-dshow-discover-source-color-range-space-etc.patch, 13.2 KB (added by Diederick Niehorster, 5 years ago)

new more complete patch

  • libavdevice/dshow.c

    From 378f5969588b7d8f9f5feba6368836bf4a9114da Mon Sep 17 00:00:00 2001
    From: Diederick Niehorster <dcnieho@gmail.com>
    Date: Mon, 31 May 2021 22:32:42 +0200
    Subject: [PATCH] avdevice/dshow: discover source color range/space/etc
    
    Enabled discovering a DirectShow device's color range, space, primaries, transfer characteristics and chroma location, if the device exposes that information. Sets them in the stream's codecpars.
    
    Signed-off-by: Diederick Niehorster <dcnieho@gmail.com>
    ---
     libavdevice/dshow.c | 230 +++++++++++++++++++++++++++++++++++++++++++-
     1 file changed, 229 insertions(+), 1 deletion(-)
    
    diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
    index 8d0a6fcc09..90aef939ef 100644
    a b  
    2929#include "libavcodec/raw.h"
    3030#include "objidl.h"
    3131#include "shlwapi.h"
     32#include "dxva.h"
    3233
    3334
    3435static enum AVPixelFormat dshow_pixfmt(DWORD biCompression, WORD biBitCount)
    static enum AVPixelFormat dshow_pixfmt(DWORD biCompression, WORD biBitCount)  
    5455    return avpriv_find_pix_fmt(avpriv_get_raw_pix_fmt_tags(), biCompression); // all others
    5556}
    5657
     58static enum AVColorRange dshow_color_range(DXVA_ExtendedFormat* fmt_info)
     59{
     60    switch (fmt_info->NominalRange)
     61    {
     62    case DXVA_NominalRange_Unknown:
     63        return AVCOL_RANGE_UNSPECIFIED;
     64    case DXVA_NominalRange_Normal:  // equal to DXVA_NominalRange_0_255
     65        return AVCOL_RANGE_JPEG;
     66    case DXVA_NominalRange_Wide:    // equal to DXVA_NominalRange_16_235
     67        return AVCOL_RANGE_MPEG;
     68    case DXVA_NominalRange_48_208:
     69        // not an ffmpeg color range
     70        return AVCOL_RANGE_UNSPECIFIED;
     71
     72    // values from MediaFoundation SDK (mfobjects.h)
     73    case 4:     // MFNominalRange_64_127
     74        // not an ffmpeg color range
     75        return AVCOL_RANGE_UNSPECIFIED;
     76
     77    default:
     78        return DXVA_NominalRange_Unknown;
     79    }
     80}
     81
     82static enum AVColorSpace dshow_color_space(DXVA_ExtendedFormat* fmt_info)
     83{
     84    enum AVColorSpace ret = AVCOL_SPC_UNSPECIFIED;
     85
     86    switch (fmt_info->VideoTransferMatrix)
     87    {
     88    case DXVA_VideoTransferMatrix_BT709:
     89        ret = AVCOL_SPC_BT709;
     90        break;
     91    case DXVA_VideoTransferMatrix_BT601:
     92        ret = AVCOL_SPC_BT470BG;
     93        break;
     94    case DXVA_VideoTransferMatrix_SMPTE240M:
     95        ret = AVCOL_SPC_SMPTE240M;
     96        break;
     97
     98    // values from MediaFoundation SDK (mfobjects.h)
     99    case 4:     // MFVideoTransferMatrix_BT2020_10
     100    case 5:     // MFVideoTransferMatrix_BT2020_12
     101        if (fmt_info->VideoTransferFunction==12)    // MFVideoTransFunc_2020_const
     102            ret = AVCOL_SPC_BT2020_CL;
     103        else
     104            ret = AVCOL_SPC_BT2020_NCL;
     105        break;
     106    }
     107
     108    if (ret == AVCOL_SPC_UNSPECIFIED)
     109    {
     110        // if color space not yet known, fall back to using primaries to guess color space
     111        switch (fmt_info->VideoPrimaries)
     112        {
     113        case DXVA_VideoPrimaries_BT709:
     114            ret = AVCOL_SPC_BT709;
     115            break;
     116        case DXVA_VideoPrimaries_BT470_2_SysM:
     117            ret = AVCOL_SPC_FCC;
     118            break;
     119        case DXVA_VideoPrimaries_BT470_2_SysBG:
     120        case DXVA_VideoPrimaries_EBU3213:   // this is PAL
     121            ret = AVCOL_SPC_BT470BG;
     122            break;
     123        case DXVA_VideoPrimaries_SMPTE170M:
     124        case DXVA_VideoPrimaries_SMPTE_C:
     125            ret = AVCOL_SPC_SMPTE170M;
     126            break;
     127        case DXVA_VideoPrimaries_SMPTE240M:
     128            ret = AVCOL_SPC_SMPTE240M;
     129            break;
     130        }
     131    }
     132
     133    return ret;
     134}
     135
     136static enum AVColorPrimaries dshow_color_primaries(DXVA_ExtendedFormat* fmt_info)
     137{
     138    switch (fmt_info->VideoPrimaries)
     139    {
     140    case DXVA_VideoPrimaries_Unknown:
     141        return AVCOL_PRI_UNSPECIFIED;
     142    case DXVA_VideoPrimaries_reserved:
     143        return AVCOL_PRI_RESERVED;
     144    case DXVA_VideoPrimaries_BT709:
     145        return AVCOL_PRI_BT709;
     146    case DXVA_VideoPrimaries_BT470_2_SysM:
     147        return AVCOL_PRI_BT470M;
     148    case DXVA_VideoPrimaries_BT470_2_SysBG:
     149    case DXVA_VideoPrimaries_EBU3213:   // this is PAL
     150        return AVCOL_PRI_BT470BG;
     151    case DXVA_VideoPrimaries_SMPTE170M:
     152    case DXVA_VideoPrimaries_SMPTE_C:
     153        return AVCOL_PRI_SMPTE170M;
     154    case DXVA_VideoPrimaries_SMPTE240M:
     155        return AVCOL_PRI_SMPTE240M;
     156
     157    // values from MediaFoundation SDK (mfobjects.h)
     158    case 9:     // MFVideoPrimaries_BT2020
     159        return AVCOL_PRI_BT2020;
     160    case 10:    // MFVideoPrimaries_XYZ
     161        return AVCOL_PRI_SMPTE428;
     162    case 11:    // MFVideoPrimaries_DCI_P3
     163        return AVCOL_PRI_SMPTE431;
     164    case 12:    // MFVideoPrimaries_ACES (Academy Color Encoding System)
     165        // not an FFmpeg color primary
     166        return AVCOL_PRI_UNSPECIFIED;
     167
     168    default:
     169        return AVCOL_PRI_UNSPECIFIED;
     170    }
     171}
     172
     173static enum AVColorTransferCharacteristic dshow_color_trc(DXVA_ExtendedFormat* fmt_info)
     174{
     175    switch (fmt_info->VideoTransferFunction)
     176    {
     177    case DXVA_VideoTransFunc_Unknown:
     178        return AVCOL_TRC_UNSPECIFIED;
     179    case DXVA_VideoTransFunc_10:
     180        return AVCOL_TRC_LINEAR;
     181    case DXVA_VideoTransFunc_18:
     182        // not an FFmpeg transfer characteristic
     183        return AVCOL_TRC_UNSPECIFIED;
     184    case DXVA_VideoTransFunc_20:
     185        // not an FFmpeg transfer characteristic
     186        return AVCOL_TRC_UNSPECIFIED;
     187    case DXVA_VideoTransFunc_22:
     188        return AVCOL_TRC_GAMMA22;
     189    case DXVA_VideoTransFunc_22_709:
     190        return AVCOL_TRC_BT709;
     191    case DXVA_VideoTransFunc_22_240M:
     192        return AVCOL_TRC_SMPTE240M;
     193    case DXVA_VideoTransFunc_22_8bit_sRGB:
     194        return AVCOL_TRC_IEC61966_2_1;
     195    case DXVA_VideoTransFunc_28:
     196        return AVCOL_TRC_GAMMA28;
     197
     198    // values from MediaFoundation SDK (mfobjects.h)
     199    case 9:     // MFVideoTransFunc_Log_100
     200        return AVCOL_TRC_LOG;
     201    case 10:    // MFVideoTransFunc_Log_316
     202        return AVCOL_TRC_LOG_SQRT;
     203    case 11:    // MFVideoTransFunc_709_sym
     204        // not an FFmpeg transfer characteristic
     205        return AVCOL_TRC_UNSPECIFIED;
     206    case 12:    // MFVideoTransFunc_2020_const
     207    case 13:    // MFVideoTransFunc_2020
     208        if (fmt_info->VideoTransferMatrix==5)   // MFVideoTransferMatrix_BT2020_12
     209            return AVCOL_TRC_BT2020_12;
     210        else
     211            return AVCOL_TRC_BT2020_10;
     212    case 14:    // MFVideoTransFunc_26
     213        // not an FFmpeg transfer characteristic
     214        return AVCOL_TRC_UNSPECIFIED;
     215    case 15:    // MFVideoTransFunc_2084
     216        return AVCOL_TRC_SMPTEST2084;
     217    case 16:    // MFVideoTransFunc_HLG
     218        return AVCOL_TRC_ARIB_STD_B67;
     219    case 17:    // MFVideoTransFunc_10_rel
     220        // not an FFmpeg transfer characteristic? Undocumented also by MS
     221        return AVCOL_TRC_UNSPECIFIED;
     222
     223    default:
     224        return AVCOL_TRC_UNSPECIFIED;
     225    }
     226}
     227
     228static enum AVChromaLocation dshow_chroma_loc(DXVA_ExtendedFormat* fmt_info)
     229{
     230    if (fmt_info->VideoChromaSubsampling == DXVA_VideoChromaSubsampling_Cosited)   // that is: (DXVA_VideoChromaSubsampling_Horizontally_Cosited | DXVA_VideoChromaSubsampling_Vertically_Cosited | DXVA_VideoChromaSubsampling_Vertically_AlignedChromaPlanes)
     231        return AVCHROMA_LOC_TOPLEFT;
     232    else if (fmt_info->VideoChromaSubsampling == DXVA_VideoChromaSubsampling_MPEG1) // that is: DXVA_VideoChromaSubsampling_Vertically_AlignedChromaPlanes
     233        return AVCHROMA_LOC_CENTER;
     234    else if (fmt_info->VideoChromaSubsampling == DXVA_VideoChromaSubsampling_MPEG2) // that is: (DXVA_VideoChromaSubsampling_Horizontally_Cosited | DXVA_VideoChromaSubsampling_Vertically_AlignedChromaPlanes)
     235        return AVCHROMA_LOC_LEFT;
     236    else if (fmt_info->VideoChromaSubsampling == DXVA_VideoChromaSubsampling_DV_PAL)// that is: (DXVA_VideoChromaSubsampling_Horizontally_Cosited | DXVA_VideoChromaSubsampling_Vertically_Cosited)
     237        return AVCHROMA_LOC_TOPLEFT;
     238    else
     239        // unknown
     240        return AVCHROMA_LOC_UNSPECIFIED;
     241}
     242
    57243static int
    58244dshow_read_close(AVFormatContext *s)
    59245{
    dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,  
    350536            VIDEO_STREAM_CONFIG_CAPS *vcaps = caps;
    351537            BITMAPINFOHEADER *bih;
    352538            int64_t *fr;
     539            DXVA_ExtendedFormat *extended_format_info = NULL;
    353540            const AVCodecTag *const tags[] = { avformat_get_riff_video_tags(), NULL };
    354541#if DSHOWDEBUG
    355542            ff_print_VIDEO_STREAM_CONFIG_CAPS(vcaps);
    dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,  
    362549                VIDEOINFOHEADER2 *v = (void *) type->pbFormat;
    363550                fr = &v->AvgTimePerFrame;
    364551                bih = &v->bmiHeader;
     552                if (v->dwControlFlags & AMCONTROL_COLORINFO_PRESENT)
     553                    extended_format_info = (DXVA_ExtendedFormat*)&v->dwControlFlags;
    365554            } else {
    366555                goto next;
    367556            }
    dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,  
    378567                } else {
    379568                    av_log(avctx, AV_LOG_INFO, "  pixel_format=%s", av_get_pix_fmt_name(pix_fmt));
    380569                }
    381                 av_log(avctx, AV_LOG_INFO, "  min s=%ldx%ld fps=%g max s=%ldx%ld fps=%g\n",
     570                av_log(avctx, AV_LOG_INFO, "  min s=%ldx%ld fps=%g max s=%ldx%ld fps=%g",
    382571                       vcaps->MinOutputSize.cx, vcaps->MinOutputSize.cy,
    383572                       1e7 / vcaps->MaxFrameInterval,
    384573                       vcaps->MaxOutputSize.cx, vcaps->MaxOutputSize.cy,
    385574                       1e7 / vcaps->MinFrameInterval);
     575                if (extended_format_info) {
     576                    enum AVColorRange col_range = dshow_color_range(extended_format_info);
     577                    enum AVColorSpace col_space = dshow_color_space(extended_format_info);
     578                    enum AVColorPrimaries col_prim = dshow_color_primaries(extended_format_info);
     579                    enum AVColorTransferCharacteristic col_trc = dshow_color_trc(extended_format_info);
     580                    enum AVChromaLocation chroma_loc = dshow_chroma_loc(extended_format_info);
     581                    if (col_range != AVCOL_RANGE_UNSPECIFIED || col_space != AVCOL_SPC_UNSPECIFIED || col_prim != AVCOL_PRI_UNSPECIFIED || col_trc != AVCOL_TRC_UNSPECIFIED) {
     582                        const char* range = av_color_range_name(col_range);
     583                        const char* space = av_color_space_name(col_space);
     584                        const char* prim = av_color_primaries_name(col_prim);
     585                        const char* trc = av_color_transfer_name(col_trc);
     586                        av_log(avctx, AV_LOG_INFO, " (%s, %s/%s/%s",
     587                            range ? range : "unknown",
     588                            space ? space : "unknown",
     589                            prim ? prim : "unknown",
     590                            trc ? trc : "unknown");
     591                        if (chroma_loc != AVCHROMA_LOC_UNSPECIFIED) {
     592                            const char* chroma = av_chroma_location_name(chroma_loc);
     593                            av_log(avctx, AV_LOG_INFO, ", %s", chroma ? chroma : "unknown");
     594                        }
     595                        av_log(avctx, AV_LOG_INFO, ")");
     596                    }
     597                    else if (chroma_loc != AVCHROMA_LOC_UNSPECIFIED) {
     598                        const char* chroma = av_chroma_location_name(chroma_loc);
     599                        av_log(avctx, AV_LOG_INFO, "(%s)", chroma ? chroma : "unknown");
     600                    }
     601                }
     602               
     603                av_log(avctx, AV_LOG_INFO, "\n");
    386604                continue;
    387605            }
    388606            if (ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO) {
    dshow_add_device(AVFormatContext *avctx,  
    9591177    if (devtype == VideoDevice) {
    9601178        BITMAPINFOHEADER *bih = NULL;
    9611179        AVRational time_base;
     1180        DXVA_ExtendedFormat* extended_format_info = NULL;
    9621181
    9631182        if (IsEqualGUID(&type.formattype, &FORMAT_VideoInfo)) {
    9641183            VIDEOINFOHEADER *v = (void *) type.pbFormat;
    dshow_add_device(AVFormatContext *avctx,  
    9681187            VIDEOINFOHEADER2 *v = (void *) type.pbFormat;
    9691188            time_base = (AVRational) { v->AvgTimePerFrame, 10000000 };
    9701189            bih = &v->bmiHeader;
     1190            if (v->dwControlFlags & AMCONTROL_COLORINFO_PRESENT)
     1191                extended_format_info = (DXVA_ExtendedFormat*)&v->dwControlFlags;
    9711192        }
    9721193        if (!bih) {
    9731194            av_log(avctx, AV_LOG_ERROR, "Could not get media type.\n");
    dshow_add_device(AVFormatContext *avctx,  
    9861207            av_log(avctx, AV_LOG_DEBUG, "attempt to use full range for HDYC...\n");
    9871208            par->color_range = AVCOL_RANGE_MPEG; // just in case it needs this...
    9881209        }
     1210        if (extended_format_info) {
     1211            par->color_range = dshow_color_range(extended_format_info);
     1212            par->color_space = dshow_color_space(extended_format_info);
     1213            par->color_primaries = dshow_color_primaries(extended_format_info);
     1214            par->color_trc = dshow_color_trc(extended_format_info);
     1215            par->chroma_location = dshow_chroma_loc(extended_format_info);
     1216        }
    9891217        if (par->format == AV_PIX_FMT_NONE) {
    9901218            const AVCodecTag *const tags[] = { avformat_get_riff_video_tags(), NULL };
    9911219            par->codec_id = av_codec_get_id(tags, bih->biCompression);