Вопрос

Мне нужно получить CMSampleBuffer для рамки OpenGL. Я использую это:

int s = 1;
        UIScreen * screen = [UIScreen mainScreen];
        if ([screen respondsToSelector:@selector(scale)]){
            s = (int)[screen scale];
        }
        const int w = viewController.view.frame.size.width/2;
        const int h = viewController.view.frame.size.height/2;
        const NSInteger my_data_length = 4*w*h*s*s;
        // allocate array and read pixels into it.
        GLubyte * buffer = malloc(my_data_length);
        glReadPixels(0, 0, w*s, h*s, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
        // gl renders "upside down" so swap top to bottom into new array.
        GLubyte * buffer2 = malloc(my_data_length);
        for(int y = 0; y < h*s; y++){
            memcpy(buffer2 + (h*s - 1 - y)*4*w*s, buffer + (4*y*w*s), 4*w*s);
        }
        free(buffer);
        CMBlockBufferRef * cm_block_buffer_ref;
        CMBlockBufferAccessDataBytes(cm_block_buffer_ref,0,my_data_length,buffer2,*buffer2);
        CMSampleBufferRef * cm_buffer;
        CMSampleBufferCreate (kCFAllocatorDefault,cm_block_buffer_ref,true,NULL,NULL,NULL,1,1,NULL,0,NULL,cm_buffer);

Я получаю exec_bad_access для cmasplebuffercreate.

Любая помощь ценится, спасибо.

Это было полезно?

Решение

Решением было использование класса AvassetWriterInputPixelBufferAdaptor.

int s = 1;
        UIScreen * screen = [UIScreen mainScreen];
        if ([screen respondsToSelector:@selector(scale)]){
            s = (int)[screen scale];
        }
        const int w = viewController.view.frame.size.width/2;
        const int h = viewController.view.frame.size.height/2;
        const NSInteger my_data_length = 4*w*h*s*s;
        // allocate array and read pixels into it.
        GLubyte * buffer = malloc(my_data_length);
        glReadPixels(0, 0, w*s, h*s, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
        // gl renders "upside down" so swap top to bottom into new array.
        GLubyte * buffer2 = malloc(my_data_length);
        for(int y = 0; y < h*s; y++){
            memcpy(buffer2 + (h*s - 1 - y)*4*w*s, buffer + (4*y*w*s), 4*w*s);
        }
        free(buffer);
        CVPixelBufferRef pixel_buffer = NULL;
        CVPixelBufferCreateWithBytes (NULL,w*2,h*2,kCVPixelFormatType_32BGRA,buffer2,4*w*s,NULL,0,NULL,&pixel_buffer);
        [av_adaptor appendPixelBuffer: pixel_buffer withPresentationTime:CMTimeMakeWithSeconds([[NSDate date] timeIntervalSinceDate: start_time],30)];

Другие советы

Почему третий параметр CMSampleBufferCreate() верно в вашем коде? Согласно документация:

Параметры

распределитель

Ассистент, который можно использовать для распределения памяти для объекта CMASMEMPLEBUFFER. Пропустите KCfalloCatordefault, чтобы использовать текущий распределитель по умолчанию.

база данных

Это может быть NULL, CMBLOCKBUFFER, без памяти без поддержки, CMBLOCKBUFFER с поддержкой памяти, но пока нет данных, или CMBLOCKBUFFER, который уже содержит данные носителя. Только в этом последнем случае (или если нулевые и numsamples равен 0), должны быть истинными.

DataReady

Указывает, содержит ли Databuffer данные среды.

Ваш cm_block_buffer_ref это передается в виде буфера, не содержит данных (вы должны получить его для безопасности, я не верю, что компилятор делает это по умолчанию), поэтому вы должны использовать false здесь.

В этом могут быть и другие вещи, но это первый предмет, который выпрыгивает на меня.

Почему двойной маллок и почему бы не заменить на месте через временный буфер?

Что-то вроде этого:

    GLubyte * raw = (GLubyte *) wyMalloc(size);
    LOGD("raw address %p", raw);
    glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, raw);
    const size_t end = h/2;
    const size_t W = 4*w;
    GLubyte row[4*w];
    for (int i=0; i <= end; i++) {
        void * top = raw + (h - i - 1)*W;
        void * bottom = raw + i*W;
        memcpy(row, top, W);
        memcpy(top, bottom, W);
        memcpy(bottom, row, W);
    }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top