6
votes

Vidéo malformée générée à partir d'une image CGIMageref normale après ApplePreFerredTrackTransform

J'essaie d'obtenir une image à partir d'une vidéo, utilisez cette image pour générer un film fixe La première étape fonctionne bien, mais la deuxième étape a généré une vidéo mal formée après que je définis AppleSpreferredtrackTransform = TRUE

Image normale extraite de la vidéo image normale extraite de la vidéo Vidéo malformée générée à partir de l'image vidéo mal formée générée à partir de l'image p>

Comment est-ce arrivé? Une image normale a généré une vidéo mal formée? En outre, si je mettez le blocageMoviefiefromimage.GeneratemoviewImageHImagehImage dans # 2 L'application s'écrasera sur cgcontextDrawimage (contexte, cgrecture (0, 0, cadresize.Width, imagesze.Height), image); p>

J'ai fait comme ci-dessous (à Swift): P>

+ (void)generateMovieWithImage:(CGImageRef)image completionBlock:(GenerateMovieWithImageCompletionBlock)handler
{

NSLog(@"%@", image);

NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent: [@"tmpgen" stringByAppendingPathExtension:@"mov"  ] ];

NSURL *videoUrl = [NSURL fileURLWithPath:path];

if ([[NSFileManager defaultManager] fileExistsAtPath:path] ) {
    NSError *error;
    if ([[NSFileManager defaultManager] removeItemAtPath:path error:&error] == NO) {
        NSLog(@"removeitematpath %@ error :%@", path, error);
    }
}


// TODO: image need to rotate programly, not in hand
int width = (int)CGImageGetWidth(image);
int height = (int)CGImageGetHeight(image);

NSError *error = nil;
AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:videoUrl
                               fileType:AVFileTypeQuickTimeMovie
                                                          error:&error];
NSParameterAssert(videoWriter);

NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                               AVVideoCodecH264, AVVideoCodecKey,
                               [NSNumber numberWithInt:width], AVVideoWidthKey,
                               [NSNumber numberWithInt:height], AVVideoHeightKey,
                               nil];
AVAssetWriterInput* writerInput = [AVAssetWriterInput
                                    assetWriterInputWithMediaType:AVMediaTypeVideo
                                    outputSettings:videoSettings] ; //retain should be removed if ARC


NSParameterAssert(writerInput);
NSParameterAssert([videoWriter canAddInput:writerInput]);
[videoWriter addInput:writerInput];

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

//    2) Start a session:
NSLog(@"start session");

[videoWriter startWriting];
[videoWriter startSessionAtSourceTime:kCMTimeZero]; //use kCMTimeZero if unsure


dispatch_queue_t mediaInputQueue = dispatch_queue_create("mediaInputQueue", NULL);
[writerInput requestMediaDataWhenReadyOnQueue:mediaInputQueue usingBlock:^{

     if ([writerInput isReadyForMoreMediaData]) {


         //    3) Write some samples:

         // Or you can use AVAssetWriterInputPixelBufferAdaptor.
         // That lets you feed the writer input data from a CVPixelBuffer
         // that’s quite easy to create from a CGImage.


         CVPixelBufferRef sampleBuffer = [self newPixelBufferFromCGImage:image];

         if (sampleBuffer) {
             CMTime frameTime = CMTimeMake(150,30);
            [adaptor appendPixelBuffer:sampleBuffer withPresentationTime:kCMTimeZero];
            [adaptor appendPixelBuffer:sampleBuffer withPresentationTime:frameTime];
             CFRelease(sampleBuffer);
         }
     }


    //    4) Finish the session:

    [writerInput markAsFinished];
    [videoWriter endSessionAtSourceTime:CMTimeMakeWithSeconds(5, 30.0) ] ; //optional can call finishWriting without specifiying endTime
    // [videoWriter finishWriting]; //deprecated in ios6
    NSLog(@"to finnish writing");

    [videoWriter finishWritingWithCompletionHandler:^{
        NSLog(@"%@",videoWriter);
        NSLog(@"finishWriting..");

        handler(videoUrl);

        ALAssetsLibrary* library = [[ALAssetsLibrary alloc] init];
        [library writeVideoAtPathToSavedPhotosAlbum:[NSURL fileURLWithPath:path] completionBlock: ^(NSURL *assetURL, NSError *error){
            if( error != nil) {
                NSLog(@"writeVideoAtPathToSavedPhotosAlbum error: %@" , error);
            }

        }];
    }]; //ios 6.0+

}];





}


+ (CVPixelBufferRef) newPixelBufferFromCGImage: (CGImageRef)image
{
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                         [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
                         [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
                         nil];
CVPixelBufferRef pxbuffer = NULL;


CGSize frameSize = CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image) );

NSLog(@"width:%f", frameSize.width);
NSLog(@"height:%f", frameSize.height);



CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, frameSize.width,
                                      frameSize.height, kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef)options,
                                      &pxbuffer);
NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);

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

CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pxdata, frameSize.width,
                                             frameSize.height, 8, 4*frameSize.width, rgbColorSpace,
                                             (CGBitmapInfo)kCGImageAlphaNoneSkipFirst
                                             );

NSParameterAssert(context);



CGContextConcatCTM(context, CGAffineTransformIdentity);
CGContextDrawImage(context, CGRectMake(0, 0, frameSize.width, frameSize.height), image);
CGColorSpaceRelease(rgbColorSpace);
CGContextRelease(context);

CVPixelBufferUnlockBaseAddress(pxbuffer, 0);

return pxbuffer;
}


0 commentaires

3 Réponses :


1
votes

Essayez ceci:

(requestTime, image, actualTime, result, error) -> Void in
     if result == AVAssetImageGeneratorResult.Succeeded {

        let img : UIImage = UIImage(CGImage: image)! // retain 
        UIImageWriteToSavedPhotosAlbum(img,nil,nil,nil) // synchron

        GenerateMovieFromImage.generateMovieWithImage(image, completionBlock:{
                (genMovieURL) in
                        handler(genMovieURL)

         })


3 commentaires

Cela ne fonctionne pas aussi, j'essaie d'utiliser mon iPad pour tester si c'est le problème de mon iPhone. Mais je pense que le problème est peut-être la matrice de transformation de l'avexte ou de la graphique.


Ajoutez ce chèque: Si (! [Vidéofriter commence]) et vérifiez le résultat de l'annexePixBuffer. Vous pouvez voir une erreur comme cette vidéoriter.Error.


Tout retour Oui, pas d'erreur enregistrée. Et j'ai essayé mais je ne peux pas faire fonctionner le programme sur mon iPad (il ne peut pas jailbreak)



1
votes

Il semble que j'ai eu une certaine amélioration.

en fonction (CVPixElbufferref) Newpixelbufferfromcgimage: (cgimageref) Image P>

Modification: P>

AVAssetWriterInput* writerInput = [AVAssetWriterInput
                                       assetWriterInputWithMediaType:AVMediaTypeVideo
                                       outputSettings:videoSettings] ; //retain should be removed if ARC


2 commentaires

Résolu par une hauteur multiple avec 2, mais je ne sais pas pourquoi: CGContextref context = cgbitmapcontextexcreate (pxdata, cadresize.width, cadresize.Height * 2, 8, 4 * cadresize.Width, rgbcolorspace (CGBITMAPInfo) KCGIMAGELPHANONESKIPFIRAT); CgcontextDrawimage (contexte, cgrectument (0, 0, cadresize.width, encadrement.Height * 2), image);


Les codeurs vidéo que vous utilisez peuvent avoir des restrictions de largeur, par ex. la largeur doit être divisible deux ou quatre. Avez-vous essayé de changer votre largeur?



1
votes

J'ai aussi eu cette erreur lorsque j'ai essayé de créer une vidéo avec un tableau d'images et de fichiers de musique. C'est dû au rapport vidéo. Alors vérifiez le cadre pour la composition vidéo. Pour votre référence: http://size43.com/jQueryvideotool.html


0 commentaires