1

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

我试图检查我提取的 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。我可能正试图在完全错误的庄园中测试这个,所以非常感谢任何帮助!

4

1 回答 1

0

感谢苹果开发人员的 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 或(如上所述)干净孔径等情况下,这些可能会有所不同。

于 2016-03-11T14:35:57.283 回答