2012-09-01 21 views
6

Mam kod, który tworzy CMBlockBuffers, a następnie tworzy CMSampleBuffer i przekazuje go do AVAssetWriterInput.Zarządzanie pamięcią CMBlockBuffer

O co chodzi z zarządzaniem pamięcią? Zgodnie z dokumentacją Apple, anything you use with 'Create' in the name should be released with CFRelease.

Jednak jeśli używam CFRelease, to moja aplikacja przerywa z parametrem "malloc: * błąd obiektu 0xblahblah: wskaźnik zwalniany nie został przydzielony.

CMBlockBufferRef tmp_bbuf = NULL; 
CMBlockBufferRef bbuf = NULL; 
CMSampleBufferRef sbuf = NULL; 
status = CMBlockBufferCreateWithMemoryBlock(
              kCFAllocatorDefault, 
              samples, 
              buflen, 
              kCFAllocatorDefault, 
              NULL, 
              0, 
              buflen, 
              0, 
              &tmp_bbuf); 

if (status != noErr || !tmp_bbuf) { 
    NSLog(@"CMBlockBufferCreateWithMemoryBlock error"); 
    return -1; 
} 
// Copy the buffer so that we get a copy of the samples in memory. 
// CMBlockBufferCreateWithMemoryBlock does not actually copy the data! 
// 
status = CMBlockBufferCreateContiguous(kCFAllocatorDefault, tmp_bbuf, kCFAllocatorDefault, NULL, 0, buflen, kCMBlockBufferAlwaysCopyDataFlag, &bbuf); 
//CFRelease(tmp_bbuf); // causes abort?! 
if (status != noErr) { 
    NSLog(@"CMBlockBufferCreateContiguous error"); 
    //CFRelease(bbuf); 
    return -1; 
} 


CMTime timestamp = CMTimeMake(sample_position_, 44100); 

status = CMAudioSampleBufferCreateWithPacketDescriptions(
    kCFAllocatorDefault, bbuf, TRUE, 0, NULL, audio_fmt_desc_, 1, timestamp, NULL, &sbuf); 

sample_position_ += n; 
if (status != noErr) { 
    NSLog(@"CMSampleBufferCreate error"); 
    return -1; 
} 
BOOL r = [audioWriterInput appendSampleBuffer:sbuf]; // AVAssetWriterInput 
//memset(&audio_buf_[0], 0, buflen); 
if (!r) { 
    NSLog(@"appendSampleBuffer error"); 
} 
//CFRelease(bbuf); 
//CFRelease(sbuf); 

Więc, w tym kodzie, powinienem używać na jakiejkolwiek stronie CFRelease?

+0

Czy kiedykolwiek to pojąć? – kevlar

+0

@kevlar I skończyło się modyfikowanie to wszystko, aby zrobić kompresję asynchroniczną przy użyciu GCD. Musiałem zwolnić te bufory. Nadal nie jestem pewien, dlaczego to się zawiesza. Jeśli obawiasz się, że masz wycieki pamięci, zeskanuj swój kod za pomocą Instruments (część XCode). – Pete

Odpowiedz

8

Kluczem jest parametrem blockAllocator do CMBlockBufferCreateWithMemoryBlock:

Allocator być wykorzystywane do alokacji memoryBlock, jeśli memoryBlock jest NULL. Jeśli parametr memoryBlock ma wartość inną niż NULL, ten przydział zostanie użyty do zwolnienia go, jeśli zostanie podany. Przekazanie wartości NULL spowoduje, że zostanie użyty domyślny przydział (ustawiony w czasie połączenia). Zdać kCFAllocatorNull, jeśli nie jest wymagana żadna wolna kolejność.

Ponieważ nie chcą „próbek” być zwalniane po zwolnieniu CMBlockBuffer, chcesz przekazać w kCFAllocatorNull jako 4. parametru tak:

status = CMBlockBufferCreateWithMemoryBlock(
              kCFAllocatorDefault, 
              samples, 
              buflen, 
              kCFAllocatorNull, 
              NULL, 
              0, 
              buflen, 
              0, 
              &tmp_bbuf); 
0
CMAudioSampleBufferCreateWithPacketDescriptions(kCFAllocatorDefault, bbuf, TRUE, 0, NULL, audio_fmt_desc_, 1, timestamp, NULL, &sbuf); 

powinno być:

CMAudioSampleBufferCreateWithPacketDescriptions(kCFAllocatorDefault, bbuf, TRUE, 0, NULL, audio_fmt_desc_, 1024, timestamp, NULL, &sbuf); 
+0

Czy należy się zastanowić, dlaczego dotyczy to zarządzania pamięcią i CFRelease? – Pete