2012-07-14 10 views
5

मैं प्रोग्रामिंग करने के लिए अपेक्षाकृत नया हूँ और यद्यपि मैं सामान्य कार्यों के साथ ठीक हूँ, मैं फिर भी वीडियो संपादनNSArray उत्पादन में विकृति है

तो मैं कुछ कोड ऑनलाइन खोज करने में कामयाब है, पूरी तरह से नया हूँ ऐसा करने के लिए नौकरियों पर गौर करें:

- (void)writeImagesAsMovie:(NSArray *)array { 
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDirectory, YES); 
NSString *documentDirectory = [paths objectAtIndex:0]; 
NSString *saveLocation = [documentDirectory stringByAppendingString:@"/temp.mov"]; 

if ([[NSFileManager defaultManager] fileExistsAtPath:saveLocation]) { 
    [[NSFileManager defaultManager] removeItemAtPath:saveLocation error:NULL]; 
} 

UIImage *first = [array objectAtIndex:0]; 

CGSize frameSize = first.size; 

NSError *error = nil; 
AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL: 
           [NSURL fileURLWithPath:saveLocation] fileType:AVFileTypeQuickTimeMovie 
                  error:&error]; 

if(error) { 
    NSLog(@"error creating AssetWriter: %@",[error description]); 
} 
NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys: 
           AVVideoCodecH264, AVVideoCodecKey, 
           [NSNumber numberWithInt:frameSize.width], AVVideoWidthKey, 
           [NSNumber numberWithInt:frameSize.height], AVVideoHeightKey, 
           nil]; 



AVAssetWriterInput *writerInput = [AVAssetWriterInput 
            assetWriterInputWithMediaType:AVMediaTypeVideo 
            outputSettings:videoSettings]; 

NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init]; 
[attributes setObject:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32ARGB] forKey:(NSString*)kCVPixelBufferPixelFormatTypeKey]; 
[attributes setObject:[NSNumber numberWithUnsignedInt:frameSize.width] forKey:(NSString*)kCVPixelBufferWidthKey]; 
[attributes setObject:[NSNumber numberWithUnsignedInt:frameSize.height] forKey:(NSString*)kCVPixelBufferHeightKey]; 

AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor 
               assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput 
               sourcePixelBufferAttributes:attributes]; 

[videoWriter addInput:writerInput]; 

// fixes all errors 
writerInput.expectsMediaDataInRealTime = YES; 

//Start a session: 
[videoWriter startWriting]; 

[videoWriter startSessionAtSourceTime:kCMTimeZero]; 

CVPixelBufferRef buffer = NULL; 
buffer = [self pixelBufferFromCGImage:[first CGImage]]; 
BOOL result = [adaptor appendPixelBuffer:buffer withPresentationTime:kCMTimeZero]; 

if (result == NO) //failes on 3GS, but works on iphone 4 
    NSLog(@"failed to append buffer"); 

if(buffer) { 
    CVBufferRelease(buffer); 
} 



//int reverseSort = NO; 
NSArray *newArray = array; 



int fps = 10; 


int i = 0; 
for (UIImage *image in newArray) 
{ 
    [NSThread sleepForTimeInterval:0.02]; 
    if (adaptor.assetWriterInput.readyForMoreMediaData) { 

     i++; 
     CMTime frameTime = CMTimeMake(1, fps); 
     CMTime lastTime = CMTimeMake(i, fps); 
     CMTime presentTime = CMTimeAdd(lastTime, frameTime); 

     UIImage *imgFrame = image;//[UIImage imageWithContentsOfFile:filePath] ; 
     buffer = [self pixelBufferFromCGImage:[imgFrame CGImage]]; 
     BOOL result = [adaptor appendPixelBuffer:buffer withPresentationTime:presentTime]; 

     if (result == NO) //failes on 3GS, but works on iphone 4 
     { 
      NSLog(@"failed to append buffer"); 
      NSLog(@"The error is %@", [videoWriter error]); 
      [NSThread sleepForTimeInterval:0.5]; 
     } 

     if(buffer) { 
      CVBufferRelease(buffer); 
     } 


    } else { 
     NSLog(@"error"); 
     i--; 
    } 
} 

//Finish the session: 
[writerInput markAsFinished]; 
[videoWriter finishWriting]; 
CVPixelBufferPoolRelease(adaptor.pixelBufferPool); 

NSLog(@"Movie created successfully"); 
} 

- (CVPixelBufferRef) pixelBufferFromCGImage: (CGImageRef) image 
{ 


    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, 
          [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, 
          nil]; 
    CVPixelBufferRef pxbuffer = NULL; 

    CVPixelBufferCreate(kCFAllocatorDefault, CGImageGetWidth(image), 
         CGImageGetHeight(image), kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef) options, 
         &pxbuffer); 

    CVPixelBufferLockBaseAddress(pxbuffer, 0); 
    void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer); 

    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef context = CGBitmapContextCreate(pxdata, CGImageGetWidth(image), 
               CGImageGetHeight(image), 8, 4*CGImageGetWidth(image), rgbColorSpace, 
               kCGImageAlphaNoneSkipFirst); 

    CGContextConcatCTM(context, CGAffineTransformMakeRotation(0)); 

    // CGAffineTransform flipVertical = CGAffineTransformMake(
    //               1, 0, 0, -1, 0, CGImageGetHeight(image) 
    //               ); 
    // CGContextConcatCTM(context, flipVertical); 



    // CGAffineTransform flipHorizontal = CGAffineTransformMake(
    //                -1.0, 0.0, 0.0, 1.0, CGImageGetWidth(image), 0.0 
    //               ); 
    // 
    // CGContextConcatCTM(context, flipHorizontal); 


    CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), 
              CGImageGetHeight(image)), image); 
    CGColorSpaceRelease(rgbColorSpace); 
    CGContextRelease(context); 

    CVPixelBufferUnlockBaseAddress(pxbuffer, 0); 

    return pxbuffer; 
} 

लेकिन समस्या यह है कि मैं कर रहा हूँ वीडियो के उत्पादन में हालांकि यह अजीब लाइनों के नीचे से पता चला है कुछ कैसे भ्रष्ट (वह चल जाता है है: enter image description here

मैं जहां यह भ्रष्ट इनपुट है कि एक जाना जाता पहलू अनुपात से मेल नहीं खाता कर सकते हैं किसी भी मदद के लिए बहुत आभारी

कई धन्यवाद

थॉमस

उत्तर

10

मैं H264 वीडियो एन्कोडिंग हार्डवेयर के साथ समस्याएं दिखाई दे दिया है किया जाएगा। उदाहरण के लिए, मेरा परीक्षण दिखाता है कि यदि एक वीडियो आयाम 128 पिक्सेल से छोटा है, तो वीडियो एन्कोड नहीं करेगा।

जो मैंने देखा है वह 128x128, 1 9 2x128, 240x160, 480x320, और अन्य है।

इस page on aspect ratios

पी.एस. देखें आप शायद AVAssetWriterInputPixelBufferAdaptor का उपयोग करना चाहेंगे क्योंकि इसमें एक पिक्सेल बफर पूल है जिसका उपयोग आप CVPixelBufferPoolCreatePixelBuffer() के माध्यम से कर सकते हैं। इसके अलावा, यह सुनिश्चित करने के लिए कि आपका एडाप्टर लेखक को लिख सकता है, आप startSessionAtSourceTime पर कॉल करने के बाद assert(adaptor.pixelBufferPool); करना चाहेंगे।

+0

बहुत बहुत धन्यवाद, पूरी तरह से काम किया! –

+0

बहुत उपयोगी। क्या आप समर्थित पहलू अनुपात के बारे में लिंक अपडेट कर सकते हैं या अधिक जानकारी साझा कर सकते हैं? मैंने देखा कि हालांकि 960x540 समर्थित है, 540x960 नहीं है; पोर्ट प्रारूपों आमतौर पर h264 द्वारा समर्थित नहीं हैं? – Morrowless

+0

कहीं भी इस पर कोई दस्तावेज नहीं है, मैंने देखा। आपको बस इसे एक विशिष्ट आकार पर आज़माएं और देखें कि यह काम करता है या नहीं। आपको किसी विशिष्ट आकार पर त्रुटि कोड नहीं मिल सकता है, लेकिन हार्डवेयर अभी भी आपके छवि डेटा को तबाह कर सकता है। एच .264 को अधिकांश आकारों के साथ काम करना चाहिए (माना जाता है कि दोनों पक्ष घटनाएं हैं), लेकिन आईओएस के साथ एच 264 में एन्कोड करने के लिए हार्डवेयर बहुत अधिक चुनौतीपूर्ण और सौदा करने में मुश्किल है। – MoDJ