2017-11-07 22 views
0

MediaMuxer 및 MediaCodec을 사용하여 카메라 및 오디오의 비디오 (H264) 데이터 및 오디오 (AAC-LC) 데이터를 MP4 파일. 그러나 MediaMuxer 객체는 때때로 mediaMuxer.stop()에서 충돌 및 오류 로그 내가에만 시도했습니다MediaMuxer를 사용하여 MP4 파일을 인코딩했으나 mediaMuxer.stop()을 호출 할 때 충돌이 발생합니다.

11-03 16:28:36.956: A/DEBUG(711): Abort message: 'frameworks/av/media/libstagefright/MPEG4Writer.cpp:2983 CHECK_LT(mCodecSpecificDataSize + 23,128) failed: 399 vs. 128' 
11-03 16:28:36.957: A/DEBUG(711):  x0 0000000000000000 x1 0000000000001184 x2 0000000000000006 x3 0000000000000000 
11-03 16:28:36.957: A/DEBUG(711):  x4 0000000000000000 x5 0000000000000001 x6 0000000000000000 x7 0000000000000000 
11-03 16:28:36.957: A/DEBUG(711):  x8 0000000000000083 x9 0000000000000000 x10 0000000000000000 x11 0000007f91bb0df8 
11-03 16:28:36.958: A/DEBUG(711):  x12 0000007f91bb0cd0 x13 0000000000000077 x14 0000007f91bb0ea8 x15 0000000000000000 
11-03 16:28:36.958: A/DEBUG(711):  x16 0000007faca8d6a8 x17 0000007faca4fb2c x18 0000007face14418 x19 0000007f91bb3510 
11-03 16:28:36.959: A/DEBUG(711):  x20 0000007f91bb3450 x21 000000000000000b x22 0000000000000006 x23 00000055a17fd260 
11-03 16:28:36.959: A/DEBUG(711):  x24 0000007f91bb1c58 x25 0000007f91bb18b4 x26 0000007f91bb1f90 x27 0000007fa9715000 
11-03 16:28:36.960: A/DEBUG(711):  x28 0000007f91bb1898 x29 0000007f91bb0d60 x30 0000007faca4d2c8 
11-03 16:28:36.960: A/DEBUG(711):  sp 0000007f91bb0d60 pc 0000007faca4fb34 pstate 0000000020000000 

가 하나의 트랙 (비디오 또는 오디오) 여러 번 인코딩입니다. mediaMuxer.stop()의 실행은 완전히 괜찮습니다.

두 트랙을 인코딩 할 때 CHECK_LT이 실패한 이유는 무엇입니까?

답변

0

좋아, 이제 대답하겠습니다.

시계를 계속 작업 한 후 AAC 트랙을 다중화 할 때 MediaMuxer.stop()이 충돌 할 수있는 많은 요인이 있음을 발견했습니다.

  1. 사용 MediaCodec 동기화 모드에서 AAC 인코딩을위한 :

    는 충돌을 방지하기 위해, 당신은 당신의 구현을위한 다음과 같은 규칙에 의해 더 나은 플레이를했다. 동기화 모드를 사용하면 여분의 메모리 카피없이 AudioRecorder에서 MediaCodec의 입력 버퍼로 오디오 샘플 (DirectByteBuffer)을 신속하게 입력 할 수 있습니다. 너무 많은 샘플을 떨어 뜨리면 MediaMuxer이 충돌합니다.

  2. 동기화 모드를 사용하는 또 다른 이유는 당신이 항상 당신이 MediaCodec에 쓰기 샘플 구현하여 writeAudioSample 방법에 사용 가능한 INPUTBUFFER를 얻을 수 있는지 확인 MediaMuxer.dequeueInputBuffer(-1)를 사용할 수 있다는 것입니다.

  3. 동기 모드를 사용하는 또 다른 이유는 을 전에 AAC 인코딩 된 데이터를 드레인해야한다는 것입니다. (길이가 2048 바이트 1024 16 비트 샘플) 값이 2048의 배수 여야,

  4. 자신에 의해 MediaFormat.KEY_MAX_INPUT_SIZE 설정 (규칙 9 참조). 일반적으로 오디오 소스의 샘플 속도, 채널 수, 응용 프로그램 및 장치의 성능에 따라 다릅니다 으로 설정합니다.

  5. 입력 샘플에 오디오 데이터가 가득 찼음을 보장하고 길이는 MediaFormat.KEY_MAX_INPUT_SIZE으로 설정 한 값이어야합니다. 그리고 마이크로 초 단위로 프레젠테이션 시간을 계산하십시오. 인접한 두 입력 샘플 사이의 표시 시간 간격은 동일해야합니다. 이 방정식 1_000_000L * KEY_MAX_INPUT_SIZE/SAMPLE_RATE/NUMBER_OF_CHANNELS/2에 의해 시료의 지속 시간을 계산하십시오. 프레젠테이션 시간을 맞추거나 으로 변경할 필요가 없습니다. long initialTime = System.nanoTime()/1000L을 사용하여 초기 시간을 가져와 MediaCodec으로 전달하는 것이 좋습니다. 따라서 다음에 샘플을 쓸 때 프레젠테이션 시간은 initialTime + 1_000_000L * KEY_MAX_INPUT_SIZE/SAMPLE_RATE/NUMBER_OF_CHANNELS/2이어야합니다.

  6. 이 부분이 가장 큰 구덩이입니다. 오디오 샘플을 MediaCodec으로 입력 할 때 프리젠 테이션 시간을 이미 설정 했더라도 AAC 인코딩 된 데이터를 MediaMuxer에 기록 할 때 프리젠 테이션 시간을 확인하십시오. AAC로 인코딩 된 데이터의 프레젠테이션 시간은 때로는 증분이 아닐 수도 있습니다. 마지막으로 작성한 프레젠테이션 시간을 MediaMuxer에 기록해야합니다. 오용 된 AAC 데이터를 찾은 경우 프레젠테이션 시간을 presentationTime = ++lastPresentationTime까지 조정하십시오.또한 제로 프리젠 테이션 타임 AAC 데이터를 얻을 수도 있습니다. 그들을 무시하라. 그들을 MediaMuxer에 쓰지 마십시오.

  7. MediaMuxer에 다른 트랙이있는 경우 각 트랙의 프레젠테이션 시간 이 동일한 범위에 있는지 확인하십시오 (몇 초 동안 오류가 있음).

  8. 하나당 AAC MediaCodecMediaMuxer. 출력물 MediaFormat을 재사용하지 마십시오.

  9. MediaMuxer.stop()을 실행하기 전에 writeAudioSample 메서드를 호출하고 을 통해 MediaCodec으로 EOS를 보내지 마십시오. 나머지 AAC 데이터를 MediaCodec에서 배출하여 MediaMuxer에 기록하십시오. MediaMuxer.stop()을 실행하고 무슨 일이 일어 났는지 확인하십시오.