Повторяющиеся элементы сцены в выводе видеосъемки iOS YUV - PullRequest
4 голосов
/ 12 декабря 2011

Я снимаю видео и обрабатываю полученные кадры YUV.вывод выглядит следующим образом: Sample from the resulting video

Хотя он обычно отображается на экране моего телефона.Но мой сверстник получает это, как на картинке выше.Каждый элемент повторяется и сдвигается на некоторое значение по горизонтали и вертикали

Мое захваченное видео имеет размер 352x288, а мой YPixelCount = 101376, UVPixelCount = YPIXELCOUNT / 4

Любая подсказка, чтобы решить эту или начальную точку дляпонять, как обрабатывать видеокадры YUV на iOS?

    NSNumber* recorderValue = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange];
    [videoRecorderSession setSessionPreset:AVCaptureSessionPreset352x288];

И это функция captureOutput

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{
    if(CMSampleBufferIsValid(sampleBuffer) && CMSampleBufferDataIsReady(sampleBuffer) && ([self isQueueStopped] == FALSE))
    {

        CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
        CVPixelBufferLockBaseAddress(imageBuffer,0); 
        UInt8 *baseAddress[3] = {NULL,NULL,NULL};
        uint8_t *yPlaneAddress = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer,0);
        UInt32 yPixelCount =  CVPixelBufferGetWidthOfPlane(imageBuffer,0) * CVPixelBufferGetHeightOfPlane(imageBuffer,0);
        uint8_t *uvPlaneAddress = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer,1);
        UInt32 uvPixelCount = CVPixelBufferGetWidthOfPlane(imageBuffer,1) * CVPixelBufferGetHeightOfPlane(imageBuffer,1);
        UInt32  p,q,r;
        p=q=r=0;
        memcpy(uPointer, uvPlaneAddress, uvPixelCount);
        memcpy(vPointer, uvPlaneAddress+uvPixelCount, uvPixelCount);

        memcpy(yPointer,yPlaneAddress,yPixelCount);
        baseAddress[0] = (UInt8*)yPointer;
        baseAddress[1] = (UInt8*)uPointer;
        baseAddress[2] = (UInt8*)vPointer;
        CVPixelBufferUnlockBaseAddress(imageBuffer,0);
    }
}

Что-то не так с приведенным вышекод?

1 Ответ

2 голосов
/ 14 декабря 2011

Ваш код выглядит не так плохо. Я вижу две ошибки и одну потенциальную проблему:

  • Неверный uvPixelCount. Формат YUV 420 означает, что существует цветовая информация для каждого блока 2 на 2 пикселя. Таким образом, правильный счет:

    uvPixelCount = (width / 2) * (height / 2);
    

    Вы пишете что-то о yPixelCount / 4, но я не вижу этого в вашем коде.

  • Информация ультрафиолетового излучения чередуется, то есть вторая плоскость попеременно содержит значения U и V. Или по-другому: есть значение U для всех четных байтовых адресов и значение V для всех нечетных байтовых адресов. Если вам действительно нужно разделить информацию U и V, memcpy не подойдет.

  • Может быть несколько дополнительных байтов после каждой строки пикселей. Вы должны использовать CVPixelBufferGetBytesPerRowOfPlane(imageBuffer, 0), чтобы получить количество байтов между двумя строками. Как следствие, один memcpy не подойдет. Вместо этого вам нужно скопировать каждую строку пикселей отдельно, чтобы избавиться от лишних байтов между строками.

Все это объясняет только часть получающегося изображения. Остальные части, вероятно, связаны с различиями между вашим кодом и ожиданиями принимающего партнера. Ты ничего не написал об этом? Действительно ли одноранговый узел нуждается в разделенных значениях U и V? Есть ли у вас сжатие 4: 2: 0? Есть ли у вас диапазон видео вместо полного диапазона?

Если вы предоставите больше информации, я могу дать вам больше подсказок.

...