2011-11-03 1 views
6

저는 ffmpeg를 사용하여 오디오 디코더를 구현하고 있습니다. 오디오를 읽거나 이미 검색을 시도하는 동안 검색 후 버퍼를 지우는 방법을 찾을 수 없으므로 검색 후 바로 오디오 읽기가 시작될 때 아티팩트가 없습니다.FFMPEG 검색으로 오디오 아티팩트가 발생합니다.

avcodec_flush_buffers가 내부 버퍼에 영향을 미치지 않는 것 같습니다. 이 문제는 모든 디코더 (mp3, aac, wma 등)에서 발생하지만 PCM/WAV (오디오가 압축되지 않았기 때문에 내부 버퍼를 사용하여 디코딩 할 데이터를 보유하지 않음)

코드 조각은 간단하다 :

av_seek_frame(audioFilePack->avContext, audioFilePack->stream, posInTimeFrame, AVSEEK_FLAG_ANY); 
avcodec_flush_buffers(audioFilePack->avContext->streams[audioFilePack->stream]->codec); 

는 설명하면서 : 내가 그렇게해야 내가 추구하고 잔류 오디오를 얻을 수 있는지에

audioFilePack->avContext = FormatContext 
audioFilePack->stream = Stream Position (also used to read audio packets) 
audioFilePack->avContext->streams[audioFilePack->stream]->codec = CodecContext for the codec used 

어떤 아이디어? 감사합니다.

+0

제발, 아이디어가 없습니까? 나는 이것을 일으키는 원인이 될지도 모르는 것에 대해 거의 아이디어없이 거의 2 주 동안 이것을 고치려고 노력하고있다. –

+0

ffmpeg-user 공식 메일 링리스트로 보낸 메시지. 아직 도움이 필요합니다. –

+0

아티팩트를 더 자세히 설명 할 수 있습니까? 클릭 수와 팝콘 수 있습니까? –

답변

3

필자는 탐색 기능이있는 오디오 플레이어를 작성한 적이 없지만, 필자가 의심하는 것은 이것입니다. 오디오의 각 패킷은 원래 사운드 웨이브 조각으로 디코딩됩니다. 일반적으로 이러한 스 니펫은 순차적으로 서로 인접 해 있으며 결과는 연속 웨이브이며 아티팩트가없는 오디오로 들립니다. 탐색 할 때 파일의 서로 다른 부분에서 두 조각을 서로 맞 닿게합니다. 이것은 일반적으로 귀가 클릭 또는 팝으로 인식하는 결과 사운드 웨이브에 불연속성을 가져 오거나, 당신이 그것을 (내가 추측하고있는) 인공물이라고 부르는대로 불연속성을 가져옵니다.

다음은 좀 더 구체적인 예입니다. 당신이 찾기 전에 오디오의 처음 25 패킷을 재생했다고 가정 해 봅시다. 패킷 25가 마지막 샘플이 12345 인 웨이브로 디코드한다고 가정 해 봅시다. 패킷 25가 스피커로 렌더링되는 동안 패킷 66을 찾습니다. 패킷 66의 첫 번째 샘플은 -23456입니다. 따라서 디지털 오디오 스트림은 탐색을 통해 12345에서 -23456으로 점프합니다. 이것은 엄청난 불연속이며 팝으로 들립니다.

필자가 찾기를 시작하기 전에 (예를 들어 패킷 26) 오프라인 버퍼에서 디코드하고 페이드 아웃을 적용한 다음 재생 대기열에 넣기 전에 하나의 추가 패킷을 가져 오는 것이 해결책이라고 생각합니다. 원하는 위치로 이동 한 후 첫 번째 패킷 (내 eaxmple에서 66)을 가져 와서 다른 오프라인 버퍼로 디코딩하고 페이드 인을 적용한 다음 재생 대기열에 넣습니다. 이것은 부드러운 음파와 무결점 추구를 보장해야합니다.

영리한 사람이라면 원하는만큼 짧게 또는 길게 페이드 아웃 및 페이드 인을 만들 수 있습니다. 나는 단지 수 밀리 세컨드만이 인공물을 막기에 충분하다고 생각한다. 이전 패킷과 새 패킷에서 크로스 페이드를 적용 할 수도 있습니다. 또한 탐색 전에 마지막 패킷의 마지막 샘플 값을 기록하고 몇 개의 샘플에서 점차적으로 0으로 내려가는 것보다는 0으로 바로 끌어 당기는 것만으로도 충분할 수 있습니다. 이것은 여분의 패킷을 디코딩하는 것보다 쉽습니다.

이 문제가 어떻게 해결 될 수 있는지 추측 할 수 있습니다. 이것은 분명히 해결 된 문제이므로 오픈 소스 오디오 플레이어를 살펴보고 그들이 추구하는 방법을 살펴 보시기 바랍니다. Audacity, Totem, Banshee, RhythmBox, Amarok 또는 VLC와 같은 프로그램이나 GStreamer와 같은 프레임 워크는 좋은 예제입니다. 그들이 주목할만한 기술을 사용하고 있다면, 여기서 주제를보고하십시오. 나는 사람들이 그들이 무엇인지를 배우기를 원할 것이라고 생각한다. 행운을 빕니다!

3

이것은 ffmpeg의 버그입니다. 내부 버퍼가 플러시되지 않으므로 플러시 후에 패킷/프레임을 가져 오면 사전 검색 데이터를 얻게됩니다. 3-16-12에서 수정 된 것으로 보이므로이 픽스를 직접 통합하거나 ffmpeg를 업그레이드 할 수 있습니다.갱신 사항으로

http://permalink.gmane.org/gmane.comp.video.libav.devel/23455

는, 버그 위에서 실제로 문제이지만, AAC와 두 번째 버그는 특히이있다.

5 개월 전, 다른 사용자가이 버그를 발견했으며 수정되었다고보고되었습니다. https://ffmpeg.org/trac/ffmpeg/ticket/420

수정 사항은 내부 버퍼를 지우는 aacdec.c에 추가되는 플러시 함수였습니다. 문제는 aacdec.c에 정의 된 두 개의 디코더가 있고 오직 하나만 플러시 함수 포인터가 주어진다는 것입니다. 다른 (보다 공통적 인) 디코더를 사용하면 여전히 제대로 지워지지 않습니다. 당신이 자신을 FFmpeg를 구축 할 수있는 위치에 있다면

는 수정 AVCodec의 ff_aac_decoder의 정의의 바닥에 .flush = 플러시 , 을 추가하는 것입니다 (파일의 맨 아래에 있습니다.)

저는 ffmpeg 애들이 알기 쉽게 메인 브랜치에 포함될 수 있도록 할 것입니다.

+0

원래의 포스터가 우연히 만나는 이유는이 – JHawkZZ

+0

대단히 감사합니다! 나는 그것을 재 컴파일하고 나의 대안적인 방법을 포기할 것이다. 그것은 추악하지만 작동한다 ... –