【问题标题】:read video metadata in objective c读取目标 c 中的视频元数据
【发布时间】:2016-06-01 01:34:20
【问题描述】:

我正在尝试查看用户选择的视频文件是否是隔行/逐行的,然后根据它进行一些操作。

我试图检查我提取的 cmsamplebuffer 是定义为顶部字段优先还是底部字段优先但是这对于所有输入都返回 null。

NSMutableDictionary *pixBuffAttributes = [[NSMutableDictionary alloc] init];
[pixBuffAttributes setObject:
 [NSNumber numberWithInt:kCVPixelFormatType_422YpCbCr8]
 forKey:(NSString*)kCVPixelBufferPixelFormatTypeKey];
myAsset = [[AVURLAsset alloc] initWithURL:urlpath options:pixBuffAttributes];
myAssetReader = [[AVAssetReader alloc] initWithAsset:myAsset error:nil];
myAssetOutput = [[AVAssetReaderTrackOutput alloc]initWithTrack:
                 [[myAsset tracksWithMediaType:AVMediaTypeVideo]
                 objectAtIndex: 0]
                outputSettings:pixBuffAttributes];
[myAssetReader addOutput:myAssetOutput];
[myAssetReader startReading];
CMSampleBufferRef ref = [myAssetOutput copyNextSampleBuffer];
if(CVBufferGetAttachments(ref, kCVImageBufferFieldDetailKey, nil) == nil)
{
    //always the case
}
else
{
    //never happens
}

不管输入文件是隔行扫描的,上面总是返回 nil。我可能正在尝试在完全错误的庄园中进行测试,因此非常感谢您的帮助!

【问题讨论】:

    标签: objective-c macos video avfoundation interlacing


    【解决方案1】:

    感谢苹果开发者的 jeschot 回答了这个问题,https://forums.developer.apple.com/thread/39029 如果其他人正试图做类似的事情来从视频中获取大部分元数据:

        CGSize inputsize = [[myAsset tracksWithMediaType:AVMediaTypeVideo][0] naturalSize];
    
        properties->m_frame_rows = inputsize.height;
        properties->m_pixel_cols = inputsize.width;
    
        CFNumberRef fieldCount = CMFormatDescriptionGetExtension((CMFormatDescriptionRef)[myAsset tracksWithMediaType:AVMediaTypeVideo][0].formatDescriptions[0], kCMFormatDescriptionExtension_FieldCount);
    
        if([(NSNumber*) fieldCount integerValue] == 1)
        {
            properties->m_interlaced = false;
            properties->m_fld2_upper = false;
        }
        else
        {
            properties->m_interlaced = true;
    
            CFPropertyListRef interlace = CMFormatDescriptionGetExtension((CMFormatDescriptionRef)[myAsset tracksWithMediaType:AVMediaTypeVideo][0].formatDescriptions[0], kCMFormatDescriptionExtension_FieldDetail);
    
            if(interlace == kCMFormatDescriptionFieldDetail_SpatialFirstLineEarly)
            {
                properties->m_fld2_upper = false;
            }
    
            if(interlace == kCMFormatDescriptionFieldDetail_SpatialFirstLineLate)
            {
                properties->m_fld2_upper = true;
            }
    
            if(interlace == kCMFormatDescriptionFieldDetail_TemporalBottomFirst)
            {
                properties->m_fld2_upper = true;
            }
    
            if(interlace == kCMFormatDescriptionFieldDetail_TemporalTopFirst)
            {
                properties->m_fld2_upper = false;
            }
        }
    
        CMTime minDuration = [myAsset tracksWithMediaType:AVMediaTypeVideo][0].minFrameDuration;
    
        int64_t fpsNumerator = minDuration.value;
        int32_t fpsDenominator = minDuration.timescale;
    
        properties->m_ticks_duration = (unsigned int) fpsNumerator;
        if (properties->m_interlaced)
        {
            properties->m_ticks_per_second = fpsDenominator * 2;
        }
        else
        {
            properties->m_ticks_per_second = fpsDenominator;
        }
    

    对于对此感到困惑的任何其他人的快速说明,如果容器具有小于完整分辨率的干净孔径等元数据,则自然尺寸并不总是图像的完整分辨率。目前正在尝试解决这个问题,但这是一个不同的问题!

    更新:

    我后来发现自然尺寸就是显示分辨率。要找到您需要解码第一帧并检查您获得的缓冲区对象的分辨率的编码分辨率。在像素纵横比 !=1 或(如上所述)干净孔径等情况下,这些可能会有所不同。

    【讨论】:

      猜你喜欢
      • 2018-03-10
      • 2011-10-03
      • 2014-12-28
      • 2013-09-24
      • 2021-01-30
      • 2012-02-26
      • 2017-04-20
      • 2015-08-23
      • 2013-08-17
      相关资源
      最近更新 更多