avassestwritterを使用したビデオ出力用のopenglのcmsamplebuffer
-
26-10-2019 - |
質問
OpenGLフレーム用のCMSAMPLEBUFFERを取得する必要があります。私はこれを使用しています:
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);
cmsamplebuffercreateのexec_bad_accessを取得します。
どんな助けも感謝しています、ありがとう。
解決
解決策は、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)];
他のヒント
なぜ3番目のパラメーターがありますか CMSampleBufferCreate()
あなたのコードで本当ですか?による ドキュメンテーション:
パラメーター
アロケーター
cmsamplebufferオブジェクトのメモリを割り当てるために使用するアロケーター。 kcfallocatordefaultを渡して、現在のデフォルトアロケーターを使用します。
データバッファー
これは、null、バッキングメモリのないcmblockbuffer、バッキングメモリを備えたcmblockbuffer、まだデータがない、または既にメディアデータを含んでいるcmblockbufferです。その最後のケースでのみ(またはnullとnumsamplesが0の場合)、Datareadyが真である必要があります。
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);
}