2012-01-23 57 views
3

我正在編寫一個庫,使用AVFoundation將資產導出到文件。我創建了一個閱讀器,一個寫入器,將輸入和輸出連接到這些輸入和輸出,然後調用輸入上的requestMediaDataWhenReadyOnQueue方法開始提取數據。提供給該方法的塊回調看起來有點像這樣:內存問題[AVAssetWriterInput requestMediaDataWhenReadyOnQueue:usingBlock:]

[input requestMediaDataWhenReadyOnQueue:queue usingBlock:^{ 
    while ([input isReadyForMoreMediaData]) { 
     CMSampleBufferRef buffer; 
     // The track has some more data for us 
     if ([reader status] == AVAssetReaderStatusReading 
       && (buffer = [output copyNextSampleBuffer])) { 
      BOOL result = [input appendSampleBuffer:buffer]; 
      CFRelease(buffer); 
      if (!result) { 
       // handle error 
       break; 
      } 
     // The track is finished, for whatever reason 
     } else { 
      [input markAsFinished]; ⬅ 
      switch ([reader status]) { 
       // inspect the status and act accordingly 
      } 
     } 
    } 
}]; 

這完全適用於iOS 5,但在iOS 4中的代碼從EXC_BAD_ACCESS標有箭頭⬅行之後死亡。經過一番探索之後,我覺得在標記輸入完成後立即銷燬該塊。 self指針在執行壞行之前是完全有效的,它會變成0xfff…或調試器報告的一些垃圾值。但是這個對象之前指出的很好,殭屍工具確認它不會被釋放。

我錯過了什麼?

+0

+1使用⬅! ʘ‿ʘ –

+0

您是否設法解決此問題? – Tonton

回答

1

看到相同(類似)的問題。 iOS5開心,iOS4.3.5,不開心。有興趣瞭解您最終發現的內容。

通過在requestMedatWhenReadyOnQueue塊之前顯式保留寫入器,寫入器輸入,讀取器,讀取器輸出並在else子句的最後明確釋放所有四個元素來實現它。

該文件確實在標記完成後表示「塊應該退出」。也許他們不是在開玩笑。如果除了退出以外的任何事情,這是一個錯誤。上述解決方法似乎雖然工作。

更新:我仍然發現它甚至在保留並釋放所有資產對象後偶爾會崩潰。正如你的問題所觀察到的那樣,它在你將標記器輸入標記爲完成後不久就崩潰了,就好像這個塊本身被解除分配一樣。而不是僅僅將該塊作爲函數的一部分。我創建了一個複製的塊屬性,它是長壽命對象的一部分。我用Block_copy初始化它,並且只在長壽命對象的析構函數中釋放它。這似乎有伎倆。從那以後,我沒有看到任何4.3.5崩潰。

+0

你可以發佈你的代碼解決這個問題嗎?有同樣的問題。 – nh32rg

0

嘗試[自我保留]作爲塊的第一行,[自釋放]作爲最後一行。

另一個關鍵問題是,如果使用requestMediaDataWhenReadyOnQueue暫停應用程序(進入後臺),則需要明確地覆蓋所有[reader status]值,因爲在應用程序重新啓動時它將失敗。在某些情況下,我發現該塊運行失敗狀態標誌不止一次。在其他具有類似代碼的文章中,有很多[保留] AV變量,然後在塊的結尾處發佈。由於該塊可以運行多次,因此該方法在應用程序進入後臺狀態時不起作用。

我發現下面在「開關」很好地工作(上圖):

   case AVAssetReaderStatusReading: 
        break; 

       case AVAssetReaderStatusCompleted: 
        [videoWriterInput markAsFinished]; 
        //do something else, like add an audio stream 
        [videoWriter finishWriting]; 
        break; 

       case AVAssetReaderStatusFailed: 
        [videoWriterInput markAsFinished]; 
        [videoWriter finishWriting]; 
        break; 

       case AVAssetReaderStatusCancelled: 
       case AVAssetReaderStatusUnknown: 
        [videoWriterInput markAsFinished]; 
        [videoWriter cancelWriting]; 
        break; 
      } 

      dispatch_sync(dispatch_get_main_queue(), ^{ 
       //hide any progress indicators 
      }); 

      break; 

比「自我」其他的一概被保留。如果需要,塊應該自動保留變量。