OpenGL CMSampleBuffer for outputting video using AVAssestWritter

I need to get a CMSampleBuffer for an OpenGL framework. I use 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, thanks.

+5
source share
3 answers

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)]; 
+6
source

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

Parameters

distributor

The allocator used to allocate memory for the CMSampleBuffer object. To pass kCFAllocatorDefault to use the current default allocator.

dataBuffer

It can be NULL, a CMBlockBuffer without backup memory, a CMBlockBuffer with backup memory but no data yet, or a CMBlockBuffer that already contains multimedia data. Only in this last case (or if NULL and numSamples are 0) if the data should be true.

dataReady

Indicates whether the dataBuffer already contains the storage medium.

Your cm_block_buffer_ref , which is passed as a buffer, does not contain data (you must NULL for security, I do not consider the compiler to do this by default), so you should use false here.

There may be other things in this, but this is the first element that jumps on me.

+1
source

Why double malloc and why not swap through a temporary buffer?

Something like that:

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

Source: https://habr.com/ru/post/888575/


All Articles