이 조금 늦게 응답을하지만 이것은 내가 다른 사람이 같은 장소에있을 수 있습니다 통해 어려움을 겪고 어려움을했다 질문입니다 (에 이동하기 때문에 영업 이익이 긴 경우에도!).
의 핵심은 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를 사용할 때 발견 한 사실은 이런 종류의 사용을 위해 실제로 만들어지지 않았다는 것입니다. 그것은 쓸모있는 모양으로 비틀어 질 수는 있지만 꼭해야 할만큼 잘 수행되지는 않습니다. 오픈 소스이기 때문에 모험은 소스를 수정하여보다 효과적인 솔루션을 만들 수 있습니다.
Windows 전용 솔루션으로 살 수있는 경우 [오디오 믹서] (https://msdn.microsoft.com/en-us/library/dd742869.aspx)를 살펴볼 수 있습니다. – IInspectable
@IInspectable 감사합니다.하지만 네트워크 스트림에서 오디오로 작업 할 수 있어야합니다. : – Roddy
제공된 모듈을 살펴볼 수 있습니다. 포함되어있는 많은 핵심 모듈이 있습니다. 모듈 구현이 너무 어렵다는 것은 아닙니다. [오디오 막대 그래프] (https : // github. 예를 들어, [float mixer (https://github.com/videolan/vlc/blob/master/modules/audio_mixer/)] 모듈을 참조하십시오. float.c)도 볼 수있는 좋은 장소가 될 것입니다.) – theB