Domanda

Ho bisogno di ottenere un CMSampleBuffer per il telaio OpenGL. Sto usando questo:

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

ho EXEC_BAD_ACCESS per CMSampleBufferCreate.

Ogni aiuto è apprezzato, grazie.

È stato utile?

Soluzione

La soluzione era quella di utilizzare la classe 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)];

Altri suggerimenti

Perché è il terzo parametro per CMSampleBufferCreate() vero nel codice? Secondo il documentazione :

Parametri

allocator

L'allocatore da utilizzare per assegnare memoria per l'CMSampleBuffer oggetto. Passare a kCFAllocatorDefault utilizzare l'allocatore predefinito corrente.

dataBuffer

Questo può essere NULL, un CMBlockBuffer senza memoria di massa, un CMBlockBuffer con memoria di massa ma i dati non ancora, o un CMBlockBuffer che contiene già i dati multimediali. Solo in questo ultimo caso (o se NULL e numSamples è 0) dovrebbe essere dataReady vero.

dataReady

Indica se dataBuffer contiene già i media i dati.

Il tuo cm_block_buffer_ref che viene passato come un buffer non contiene dati (si dovrebbe NULL per la sicurezza, non credo che il compilatore lo fa di default), quindi si dovrebbe usare false qui.

Ci possono essere altre cose di sbagliato in questo, ma questo è il primo elemento che salta fuori di me.

Perché il doppio malloc e perché no di swap in atto attraverso un buffer temporaneo?

Qualcosa di simile a questo:

    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);
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top