2016-07-01 3 views
1

로 오디오 측광.나는 비디오 스트림을 표시하는 윈도우 C++ 응용 프로그램에서 LibVLC을 사용하고 LibVLC

나는 내 응용 프로그램의 다른 부분에 전달 미터링 데이터를 생성하기 위해 들어오는 오디오 샘플을 모니터링 할. 나는이 종류의 libvlc_audio_set_callbacks을 가지고있다. 출력 오디오를 모니터하고있어, 뮤트 등의 영향을 받는다. b : 이것을 가능하게하면, 오디오를들을 수 없다. (시피, 이것은 설명 된 행동이다. 문서에서).

실제로 LibVLC API를 사용하여이 작업을 수행하는 방법이 있습니까, 아니면 오디오 필터 플러그인을 작성해야합니까?

또는, 내가 사용할 수있는 플러그인을 일부 기존의 일반적인 '스니핑 오디오'이 있습니까?

+0

Windows 전용 솔루션으로 살 수있는 경우 [오디오 믹서] (https://msdn.microsoft.com/en-us/library/dd742869.aspx)를 살펴볼 수 있습니다. – IInspectable

+0

@IInspectable 감사합니다.하지만 네트워크 스트림에서 오디오로 작업 할 수 있어야합니다. : – Roddy

+1

제공된 모듈을 살펴볼 수 있습니다. 포함되어있는 많은 핵심 모듈이 있습니다. 모듈 구현이 너무 어렵다는 것은 아닙니다. [오디오 막대 그래프] (https : // github. 예를 들어, [float mixer (https://github.com/videolan/vlc/blob/master/modules/audio_mixer/)] 모듈을 참조하십시오. float.c)도 볼 수있는 좋은 장소가 될 것입니다.) – theB

답변

1

이 조금 늦게 응답을하지만 이것은 내가 다른 사람이 같은 장소에있을 수 있습니다 통해 어려움을 겪고 어려움을했다 질문입니다 (에 이동하기 때문에 영업 이익이 긴 경우에도!).

의 핵심은 smem 플러그인을 사용하는 것입니다. 이렇게하면 재생되는 오디오 및 비디오를 추적 할 수 있습니다 (몇 가지 심각한 문제가 있음, 아래 참조). 동시에 재생하고 미터기를 사용하려면 스트림을 duplicate (분할)해야합니다. 다음은 출력 문자열이 그렇게 사용하는 것입니다

std::ostringstream outstream; 
outstream << ":sout=#duplicate{dst=std{access=file,dst=\"" << filepath << "\"},dst=\"transcode{acodec=s16l}:" << createFrameCallbackString(true) << "\"}"; 
libvlc_media_add_option(media, outstream.str().c_str()); 

우리는 스트림이 분리되어있는 출력 체인, duplicate에 따라서 전화를 작성해야합니다. 중복 된 곳에는 두 개의 대상이 있습니다.

outstream << ":sout=#duplicate{dst=...,dst=...}"; 

필자는 예를 들어 비디오 창에 파일을 표시하는 대신 녹음하여 자신의 첫 번째 대상을 바꾸려고합니다. 두 번째 목적지는 우리가 오디오를 전송 (및/또는 비디오) smem를 사용하는 방법을 콜백하는 곳입니다 :

"..., dst=\"transcode{acodec=s16l}:" << createFrameCallbackString(true) << "\"}" 

참고 smem 오디오에 대해서는, PCM에 있어야한다 (또는 그래서 문서가 보인다), 그래서 16 비트 리틀 엔디안 (s16l)의 부호있는 코드로 변환합니다. (결국 1이 아닌 L입니다.) 트랜스 코딩의 오버 헤드 비용은 얼마입니까? 내 테스트에서는 꽤 작아 보입니다.하지만 성능에 대한 우려가 있다면 가치가 있습니다. smem에 대한 출력 체인을 구성

다음과 같습니다

class Player 
{ 
//callback for frame monitoring 
static void prerendercb(void *data, unsigned char** buffer, size_t size) 
{ 
    //we must allocate a buffer in order for postrender to be called 
    *buffer = (uint8_t *)malloc(size); 
} 

static void postrendercb(void *data, unsigned char* buffer, int width, int height, int pitch, size_t size, int64_t pts) 
{ 
    Player* context = (Player*)data; 
    //free the buffer 
    free(buffer); 
    //notify context of frame for processing 
    context->OnFrame(/*pass it whatever information you need*/); 
} 
static void audio_prerendercb(void* data, unsigned char** buffer, size_t size) 
{ 
    *buffer = (uint8_t *)malloc(size); 
} 
static void audio_postrendercb(void* data, unsigned char* buffer, unsigned int channels, unsigned int rate, 
     unsigned int nb_samples, unsigned int bits_per_sample, size_t size, int64_t pts) 
{ 
    Player* context = (Player*)data; 
    //free the buffer 
    free(buffer); 
    //notify context 
    context->OnAudioFrame(/*whatever data is needed*/); 
} 

//Get an smem string for the audio/video callbacks 
std::string Player::createFrameCallbackString(bool timesync) const 
{ 
    std::ostringstream text; 
    text << 
     "smem{" << "video-prerender-callback=" << ((long long int)(intptr_t)(void*)&prerendercb) << "," << 
         "video-postrender-callback=" << ((long long int)(intptr_t)(void*)&postrendercb) << "," << 
         "video-data=" << ((long long int)(intptr_t)(void*)this) << "," << 
         "audio-prerender-callback=" << ((long long int)(intptr_t)(void*)&audio_prerendercb) << "," << 
         "audio-postrender-callback=" << ((long long int)(intptr_t)(void*)&audio_postrendercb) << "," << 
         "audio-data=" << ((long long int)(intptr_t)(void*)this) << "," << 
         "time-sync=" << (timesync ? "1" : "0") << 
         "}"; 

    return text.str(); 
} 

} 

주의 사항을
을 제외하고 트랜스 코딩 문제에서, 당신은 당신이 그것을 여부에 대한 관심 여부를 버퍼의 데이터를 할당 할 필요가 있다는 사실 가장 큰 문제는 libVLC가 프레임 을 비동기 적으로으로 처리한다는 것입니다. 결과적으로 10, 15 프레임이 한 번에 처리되고 잠시 동안 아무 것도 보지 못하고 또 다른 버스트가 발생하는 곳에서 버스트가 발생하는 경향이 있습니다. 이것은 확실히 캐시 크기 (libVLC에 몇 가지가 있음)의 영향을 받지만 캐시 크기를 가능한 한 낮게 설정하더라도 적어도 2 또는 3 프레임 이상 버스트가 발생합니다. 당신의 출력 체인 시세 및 브라켓에 관심을 지불하는 것입니다 구성 할 때

libvlc_media_add_option(media, ":clock-synchro=0"); //this setting is critical for realtime processing of audio stream! 
libvlc_media_add_option(media, ":clock-jitter=0"); 

또 다른주의 : 이 옵션을 설정하면 많은 도움이됩니다. 어딘가에 출판 된 가이드 라인이있을 수 있지만 그것은 나를위한 약간의 시행 착오였습니다.

마지막으로,에 time-sync 옵션을 사용할 때 합당한 차이를 발견하지 못했습니다. 나는 그것이 무엇으로 설정되었는지는 중요하다고 생각하지만 어떻게 결정할 수 없었습니다.

libVLC를 사용할 때 발견 한 사실은 이런 종류의 사용을 위해 실제로 만들어지지 않았다는 것입니다. 그것은 쓸모있는 모양으로 비틀어 질 수는 있지만 꼭해야 할만큼 잘 수행되지는 않습니다. 오픈 소스이기 때문에 모험은 소스를 수정하여보다 효과적인 솔루션을 만들 수 있습니다.

+0

와우. 오랜 시간이 지난 후에 좋은 대답을 기대하지 못했습니다. 그것을 줄 것이다 .... – Roddy