Pregunta

Necesito obtener un CMSampleBuffer para el marco OpenGL. Estoy usando esto:

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);

Obtengo exec_bad_access para cmsampleBufferCreate.

Cualquier ayuda se agradece, gracias.

¿Fue útil?

Solución

La solución era usar la clase 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)];

Otros consejos

¿Por qué el tercer parámetro es CMSampleBufferCreate() ¿Es cierto en su código? De acuerdo con la documentación:

Parámetros

asignador

El asignador para usar para asignar memoria para el objeto CMSampleBuffer. Pase KCFallOCATORDEFAULT para usar el asignador predeterminado actual.

databufer

Esto puede ser nulo, un cmblockbuffer sin memoria de respaldo, un cmblockbuffer con memoria de respaldo pero aún sin datos, o un cmblockbuffer que ya contiene los datos de los medios. Solo en ese último caso (o si NULL y NUMSPLES es 0) debería ser cierto.

datarady

Indica si Databuffer ya contiene los datos de los medios.

Su cm_block_buffer_ref que se está pasando como un búfer no contiene datos (debe anularlo por seguridad, no creo que el compilador lo haga de forma predeterminada), por lo que debe usar false aquí.

Puede haber otras cosas mal en esto, pero ese es el primer elemento que salta a mí.

¿Por qué el doble malloc y por qué no cambiar en su lugar a través de un búfer temporal?

Algo como esto:

    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);
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top