2011-01-11 17 views
5

मैं CMSampleBuffer की सामग्री को संशोधित करना चाहता हूं और फिर इसे AVAssetWriter/AVAssetWriterInput के साथ फ़ाइल में लिखना चाहता हूं।CMSampleBuffer सामग्री को संशोधित करने का सबसे प्रभावी तरीका

मैं ऐसा करता हूं कोर कोरिक्स बिटमैप संदर्भ बनाकर और फिर इसमें ड्राइंग करके, लेकिन यह बहुत धीमा है। विशेष रूप से, मुझे बफर में एक छवि खींचने की आवश्यकता है।

तो क्या कोई इसे किसी और प्रकार के संकेत या सुझाव प्रदान कर सकता है कि इसे और अधिक कुशलता से कैसे किया जाए?

मैंने इसे पूरा करने के लिए ओपनजीएल का उपयोग करने के बारे में सोचा, यानी, पहले CMSampleBuffer से बनावट बनाओ। फिर बनावट बी प्रस्तुत करें, जिसे मैं ड्रॉ करना चाहता हूं, बनावट ए में बनाकर, फिर ओपनजीएल से बनावट ए का समर्थन करने वाले डेटा को पुनर्प्राप्त करें और आखिरकार उस डेटा को AVAssetWriter/AVAssetWriterInput पर सौंप दें। लेकिन दस्तावेज़ कहते हैं कि GPU से वापस CPU तक बनावट डेटा स्थानांतरित करना थोड़े महंगा है।

तो, इस पर कैसे पहुंचे इस पर कोई सुझाव?

अग्रिम धन्यवाद

उत्तर

8

ओपनजीएल शायद जाने का रास्ता है। हालांकि, बनावट के बजाए ऑफस्क्रीन फ्रेमबफर को प्रस्तुत करने के लिए यह थोड़ा और अधिक कुशल हो सकता है।

एक नमूना बफर से एक बनावट निकालने के लिए:

// Note the caller is responsible for calling glDeleteTextures on the return value. 
- (GLuint)textureFromSampleBuffer:(CMSampleBufferRef)sampleBuffer { 
    GLuint texture = 0; 

    glGenTextures(1, &texture); 
    glBindTexture(GL_TEXTURE_2D, texture); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 

    CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    CVPixelBufferLockBaseAddress(pixelBuffer, 0); 
    int width = CVPixelBufferGetWidth(pixelBuffer); 
    int height = CVPixelBufferGetHeight(pixelBuffer); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, CVPixelBufferGetBaseAddress(pixelBuffer)); 
    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0); 

    return texture; 
} 

ओपन के माध्यम से बनावट संसाधन के लिए, आप तो कुछ इस तरह कर सकता है:

// This function exists to free the malloced data when the CGDataProviderRef is 
// eventually freed. 
void dataProviderFreeData(void *info, const void *data, size_t size){ 
    free((void *)data); 
} 

// Returns an autoreleased CGImageRef. 
- (CGImageRef)processTexture:(GLuint)texture width:(int)width height:(int)height { 
    CGImageRef newImage = NULL; 

    // Set up framebuffer and renderbuffer. 
    GLuint framebuffer; 
    glGenFramebuffers(1, &framebuffer); 
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 

    GLuint colorRenderbuffer; 
    glGenRenderbuffers(1, &colorRenderbuffer); 
    glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer); 
    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, width, height); 
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer); 

    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 
    if (status != GL_FRAMEBUFFER_COMPLETE) { 
     NSLog(@"Failed to create OpenGL frame buffer: %x", status); 
    } else { 
     glViewport(0, 0, width, height); 
     glClearColor(0.0,0.0,0.0,1.0); 
     glClear(GL_COLOR_BUFFER_BIT); 

     // Do whatever is necessary to actually draw the texture to the framebuffer 
     [self renderTextureToCurrentFrameBuffer:texture]; 

     // Read the pixels out of the framebuffer 
     void *data = malloc(width * height * 4); 
     glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); 

     // Convert the data to a CGImageRef. Note that CGDataProviderRef takes 
     // ownership of our malloced data buffer, and the CGImageRef internally 
     // retains the CGDataProviderRef. Hence the callback above, to free the data 
     // buffer when the provider is finally released. 
     CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, data, width * height * 4, dataProviderFreeData); 
     CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); 
     newImage = CGImageCreate(width, height, 8, 32, width*4, colorspace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast, dataProvider, NULL, true, kCGRenderingIntentDefault); 
     CFRelease(dataProvider); 
     CGColorSpaceRelease(colorspace); 

     // Autorelease the CGImageRef 
     newImage = (CGImageRef)[NSMakeCollectable(newImage) autorelease]; 
    } 

    // Clean up the framebuffer and renderbuffer. 
    glDeleteRenderbuffers(1, &colorRenderbuffer); 
    glDeleteFramebuffers(1, &framebuffer); 

    return newImage; 
} 
संबंधित मुद्दे