CMSampleBuffer from OpenGL for video output with AVAssestWritter

▼魔方 西西 提交于 2020-01-01 11:46:28

问题


I need to get a CMSampleBuffer for the OpenGL frame. I'm using this:

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

I get EXEC_BAD_ACCESS for CMSampleBufferCreate.

Any help is appreciated, thank you.


回答1:


The solution was to use the AVAssetWriterInputPixelBufferAdaptor class.

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



回答2:


Why is the third parameter to CMSampleBufferCreate() true in your code? According to the documentation:

Parameters

allocator

The allocator to use to allocate memory for the CMSampleBuffer object. Pass kCFAllocatorDefault to use the current default allocator.

dataBuffer

This can be NULL, a CMBlockBuffer with no backing memory, a CMBlockBuffer with backing memory but no data yet, or a CMBlockBuffer that already contains the media data. Only in that last case (or if NULL and numSamples is 0) should dataReady be true.

dataReady

Indicates whether dataBuffer already contains the media data.

Your cm_block_buffer_ref that is being passed in as a buffer contains no data (you should NULL it for safety, I don't believe the compiler does that by default), so you should use false here.

There may be other things wrong with this, but that's the first item that leaps out at me.




回答3:


Why the double malloc and why not swap in place via a temp buffer?

Something like this:

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


来源:https://stackoverflow.com/questions/4824173/cmsamplebuffer-from-opengl-for-video-output-with-avassestwritter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!