videotoolbox: expose colorimetry information
authorFelix Paul Kühne <fkuehne@videolan.org>
Sun, 17 Apr 2016 11:52:50 +0000 (14:52 +0300)
committerFelix Paul Kühne <fkuehne@videolan.org>
Sun, 17 Apr 2016 11:53:10 +0000 (14:53 +0300)
modules/codec/videotoolbox.m

index 9afabe5..840876e 100644 (file)
@@ -122,6 +122,8 @@ struct decoder_sys_t
     NSMutableDictionary         *outputFrames;
     bool                        b_zero_copy;
     bool                        b_enable_temporal_processing;
+
+    bool                        b_format_propagated;
 };
 
 #pragma mark - start & stop
@@ -642,6 +644,8 @@ static void StopVideoToolbox(decoder_t *p_dec)
             CFRelease(p_sys->session);
             p_sys->session = nil;
         }
+
+        p_sys->b_format_propagated = false;
     }
 
     if (p_sys->videoFormatDescription != nil) {
@@ -1174,16 +1178,75 @@ static void DecoderCallback(void *decompressionOutputRefCon,
     decoder_t *p_dec = (decoder_t *)decompressionOutputRefCon;
     decoder_sys_t *p_sys = p_dec->p_sys;
 
+    if (unlikely(!p_sys->b_format_propagated)) {
+        CFDictionaryRef attachments = CVBufferGetAttachments(imageBuffer, kCVAttachmentMode_ShouldPropagate);
+        NSDictionary *attachmentDict = (NSDictionary *)attachments;
 #ifndef NDEBUG
-    static BOOL outputdone = NO;
-    if (!outputdone) {
-        /* attachments include all kind of debug info */
-        CFDictionaryRef attachments = CVBufferGetAttachments(imageBuffer,
-                                                             kCVAttachmentMode_ShouldPropagate);
         NSLog(@"%@", attachments);
-        outputdone = YES;
-    }
 #endif
+        if (attachmentDict != nil) {
+            if (attachmentDict.count > 0) {
+                p_sys->b_format_propagated = true;
+
+                NSString *colorSpace = attachmentDict[(NSString *)kCVImageBufferYCbCrMatrixKey];
+                if (colorSpace != nil) {
+                    if ([colorSpace isEqualToString:(NSString *)kCVImageBufferYCbCrMatrix_ITU_R_601_4])
+                        p_dec->fmt_out.video.space = COLOR_SPACE_BT601;
+                    else if ([colorSpace isEqualToString:(NSString *)kCVImageBufferYCbCrMatrix_ITU_R_709_2])
+                        p_dec->fmt_out.video.space = COLOR_SPACE_BT709;
+                    else
+                        p_dec->fmt_out.video.space = COLOR_SPACE_UNDEF;
+                }
+
+                NSString *colorprimary = attachmentDict[(NSString *)kCVImageBufferColorPrimariesKey];
+                if (colorprimary != nil) {
+                    if ([colorprimary isEqualToString:(NSString *)kCVImageBufferColorPrimaries_SMPTE_C] ||
+                        [colorprimary isEqualToString:(NSString *)kCVImageBufferColorPrimaries_EBU_3213])
+                        p_dec->fmt_out.video.primaries = COLOR_PRIMARIES_BT601_625;
+                    else if ([colorprimary isEqualToString:(NSString *)kCVImageBufferColorPrimaries_ITU_R_709_2])
+                        p_dec->fmt_out.video.primaries = COLOR_PRIMARIES_BT709;
+                    else if ([colorprimary isEqualToString:(NSString *)kCVImageBufferColorPrimaries_P22])
+                        p_dec->fmt_out.video.primaries = COLOR_PRIMARIES_DCI_P3;
+                    else
+                        p_dec->fmt_out.video.primaries = COLOR_PRIMARIES_UNDEF;
+                }
+
+                NSString *transfer = attachmentDict[(NSString *)kCVImageBufferTransferFunctionKey];
+                if (transfer != nil) {
+                    if ([transfer isEqualToString:(NSString *)kCVImageBufferTransferFunction_ITU_R_709_2] ||
+                        [transfer isEqualToString:(NSString *)kCVImageBufferTransferFunction_SMPTE_240M_1995])
+                        p_dec->fmt_out.video.transfer = TRANSFER_FUNC_BT709;
+                    else
+                        p_dec->fmt_out.video.transfer = TRANSFER_FUNC_UNDEF;
+                }
+
+                NSString *chromaLocation = attachmentDict[(NSString *)kCVImageBufferChromaLocationTopFieldKey];
+                if (chromaLocation != nil) {
+                    if ([chromaLocation isEqualToString:(NSString *)kCVImageBufferChromaLocation_Left] ||
+                        [chromaLocation isEqualToString:(NSString *)kCVImageBufferChromaLocation_DV420])
+                        p_dec->fmt_out.video.chroma_location = CHROMA_LOCATION_LEFT;
+                    else if ([chromaLocation isEqualToString:(NSString *)kCVImageBufferChromaLocation_Center])
+                        p_dec->fmt_out.video.chroma_location = CHROMA_LOCATION_CENTER;
+                    else if ([chromaLocation isEqualToString:(NSString *)kCVImageBufferChromaLocation_TopLeft])
+                        p_dec->fmt_out.video.chroma_location = CHROMA_LOCATION_TOP_LEFT;
+                    else if ([chromaLocation isEqualToString:(NSString *)kCVImageBufferChromaLocation_Top])
+                        p_dec->fmt_out.video.chroma_location = CHROMA_LOCATION_TOP_CENTER;
+                    else
+                        p_dec->fmt_out.video.chroma_location = CHROMA_LOCATION_UNDEF;
+                }
+                if (p_dec->fmt_out.video.chroma_location == CHROMA_LOCATION_UNDEF) {
+                    chromaLocation = attachmentDict[(NSString *)kCVImageBufferChromaLocationBottomFieldKey];
+                    if (chromaLocation != nil) {
+                        if ([chromaLocation isEqualToString:(NSString *)kCVImageBufferChromaLocation_BottomLeft])
+                            p_dec->fmt_out.video.chroma_location = CHROMA_LOCATION_BOTTOM_LEFT;
+                        else if ([chromaLocation isEqualToString:(NSString *)kCVImageBufferChromaLocation_Bottom])
+                            p_dec->fmt_out.video.chroma_location = CHROMA_LOCATION_BOTTOM_CENTER;
+                    }
+                }
+                decoder_UpdateVideoFormat(p_dec);
+            }
+        }
+    }
 
     if (status != noErr) {
         msg_Warn(p_dec, "decoding of a frame failed (%i, %u)", status, (unsigned int) infoFlags);