objective c - AvAssetReader and Writer to overlay video -


i trying overlay recorded video avassetreader , avassetwriter images. following tutorial, able copy video (and audio) new file. objective overlay of initial video frames images code:

while ([assetwritervideoinput isreadyformoremediadata] && !completedorfailed)             {                 // next video sample buffer, , append output file.                 cmsamplebufferref samplebuffer = [assetreadervideooutput copynextsamplebuffer];                  cvpixelbufferref pixelbuffer = cmsamplebuffergetimagebuffer(samplebuffer);                 cvpixelbufferlockbaseaddress(pixelbuffer, 0);                 eaglcontext *eaglcontext = [[eaglcontext alloc] initwithapi:keaglrenderingapiopengles2];                 cicontext *cicontext = [cicontext contextwitheaglcontext:eaglcontext options:@{kcicontextworkingcolorspace : [nsnull null]}];                 uifont *font = [uifont fontwithname:@"helvetica" size:40];                 nsdictionary *attributes = @{nsfontattributename:font, nsforegroundcolorattributename:[uicolor lighttextcolor]};                 uiimage *img = [self imagefromtext:@"test" :attributes];                  ciimage *filteredimage = [[ciimage alloc] initwithcgimage:img.cgimage];                  [cicontext render:filteredimage tocvpixelbuffer:pixelbuffer bounds:[filteredimage extent] colorspace:cgcolorspacecreatedevicergb()];                   cvpixelbufferunlockbaseaddress(pixelbuffer, 0);                  if (samplebuffer != null)                 {                     bool success = [assetwritervideoinput appendsamplebuffer:samplebuffer];                     cfrelease(samplebuffer);                     samplebuffer = null;                     completedorfailed = !success;                 }                 else                 {                     completedorfailed = yes;                 }             } 

and create image text:

-(uiimage *)imagefromtext:(nsstring *)text :(nsdictionary *)attributes{ cgsize size = [text sizewithattributes:attributes]; uigraphicsbeginimagecontextwithoptions(size, no, 0.0); [text drawatpoint:cgpointmake(0.0, 0.0) withattributes:attributes]; uiimage *image = uigraphicsgetimagefromcurrentimagecontext(); uigraphicsendimagecontext(); return image; } 

the video , audio copied, haven't text on video.

question 1: why code not working?

moreover, want able check timecode of current read frame. example insert text current timecode in video.

i try code following tutorial:

        avasset *localasset = [avasset assetwithurl:murl];     nserror *localerror;     avassetreader *assetreader = [[avassetreader alloc] initwithasset:localasset error:&localerror];     bool success = (assetreader != nil);      // create asset reader output first timecode track of asset     if (success) {         avassettrack *timecodetrack = nil;          // grab first timecode track, if asset has them         nsarray *timecodetracks = [localasset trackswithmediatype:avmediatypetimecode];         if ([timecodetracks count] > 0)             timecodetrack = [timecodetracks objectatindex:0];          if (timecodetrack) {             avassetreadertrackoutput *timecodeoutput = [avassetreadertrackoutput assetreadertrackoutputwithtrack:timecodetrack outputsettings:nil];             [assetreader addoutput:timecodeoutput];         } else {             nslog(@"%@ has no timecode tracks", localasset);         }     } 

but log:

[...] has no timecode tracks

question 2: why video hasn't avmediatypetimecode? ad how can current frame timecode?

thanks help

i found solutions:

to overlay video frames, need fix decompression settings:

nsstring* key = (nsstring*)kcvpixelbufferpixelformattypekey; nsnumber* value = [nsnumber numberwithunsignedint:kcvpixelformattype_32bgra]; nsdictionary* decompressionvideosettings = [nsdictionary dictionarywithobject:value forkey:key]; // if there video track read, set decompression settings yuv , create asset reader output. assetreadervideooutput = [avassetreadertrackoutput assetreadertrackoutputwithtrack:assetvideotrack outputsettings:decompressionvideosettings]; 

to frame timestamp, have read video informations , use counter increment current timestamp:

durationseconds = cmtimegetseconds(asset.duration); timeperframe = 1.0 / (float64)assetvideotrack.nominalframerate; totalframes = durationseconds * assetvideotrack.nominalframerate; 

then in loop

while ([assetwritervideoinput isreadyformoremediadata] && !completedorfailed)

you can found timestamp:

cmsamplebufferref samplebuffer = [assetreadervideooutput copynextsamplebuffer]; if (samplebuffer != null){ cvpixelbufferref pixelbuffer = cmsamplebuffergetimagebuffer(samplebuffer); if (pixelbuffer) { float64 secondsin = ((float)counter/totalframes)*durationseconds; cmtime imagetimeestimate = cmtimemakewithseconds(secondsin, 600); mergetime = cmtimegetseconds(imagetimeestimate);                                     counter++; } } 

i hope help!


Comments

Popular posts from this blog

javascript - jQuery: Add class depending on URL in the best way -

caching - How to check if a url path exists in the service worker cache -

Redirect to a HTTPS version using .htaccess -