Читать метаданные видео в цели c
Я пытаюсь увидеть, является ли видеофайл, выбранный пользователем, чересстрочным / прогрессивным, а затем выполнить некоторые манипуляции в зависимости от этого.
Я попытался проверить, определен ли извлеченный мной cmsamplebuffer как верхнее поле первым или нижнее поле первым, однако это возвращает ноль для всех входных данных.
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
}
независимо от чересстрочного ввода входного файла выше всегда возвращает ноль. Я, вероятно, пытаюсь проверить это в совершенно неправильном поместье, поэтому любая помощь очень ценится!
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 или (как описано выше) чистая апертура.