diff --git a/plugins/win-dshow/ffmpeg-decode.c b/plugins/win-dshow/ffmpeg-decode.c index 622fc9f48..f8d7b6e44 100644 --- a/plugins/win-dshow/ffmpeg-decode.c +++ b/plugins/win-dshow/ffmpeg-decode.c @@ -16,6 +16,8 @@ ******************************************************************************/ #include "ffmpeg-decode.h" +#include +#include #include int ffmpeg_decode_init(struct ffmpeg_decode *decode, enum AVCodecID id) @@ -107,8 +109,33 @@ static inline void copy_data(struct ffmpeg_decode *decode, uint8_t *data, memcpy(decode->packet_buffer, data, size); } +static void do_idiotic_lgp_audio_packet_realignment( + struct ffmpeg_decode *decode, long long *ts) +{ + uint64_t new_ts = (uint64_t)*ts; + util_uint128_t u128; + + if (!decode->lgp_started) { + decode->lgp_start_ts = new_ts; + decode->lgp_next_expected_ts = new_ts; + decode->lgp_started = true; + } + + if (llabs(decode->lgp_next_expected_ts - new_ts) < 3000000ULL) { + *ts = (long long)decode->lgp_next_expected_ts; + } else { + decode->lgp_start_ts = new_ts; + decode->lgp_frames_since_start = 0; + } + + decode->lgp_frames_since_start += (uint64_t)decode->frame->nb_samples; + u128 = util_mul64_64(decode->lgp_frames_since_start, 10000000ULL); + decode->lgp_next_expected_ts = decode->lgp_start_ts + + util_div128_32(u128, (uint32_t)decode->frame->sample_rate).low; +} + int ffmpeg_decode_audio(struct ffmpeg_decode *decode, - uint8_t *data, size_t size, + uint8_t *data, size_t size, long long *ts, struct obs_source_audio *audio, bool *got_output) { @@ -148,6 +175,9 @@ int ffmpeg_decode_audio(struct ffmpeg_decode *decode, if (audio->format == AUDIO_FORMAT_UNKNOWN) return 0; + if (decode->fix_braindead_lgp_audio_packet_stupidity) + do_idiotic_lgp_audio_packet_realignment(decode, ts); + *got_output = true; return len; } diff --git a/plugins/win-dshow/ffmpeg-decode.h b/plugins/win-dshow/ffmpeg-decode.h index aca1be52e..ba5d76262 100644 --- a/plugins/win-dshow/ffmpeg-decode.h +++ b/plugins/win-dshow/ffmpeg-decode.h @@ -44,13 +44,19 @@ struct ffmpeg_decode { uint8_t *packet_buffer; size_t packet_size; + + uint64_t lgp_start_ts; + uint64_t lgp_frames_since_start; + uint64_t lgp_next_expected_ts; + bool lgp_started; + bool fix_braindead_lgp_audio_packet_stupidity; }; extern int ffmpeg_decode_init(struct ffmpeg_decode *decode, enum AVCodecID id); extern void ffmpeg_decode_free(struct ffmpeg_decode *decode); extern int ffmpeg_decode_audio(struct ffmpeg_decode *decode, - uint8_t *data, size_t size, + uint8_t *data, size_t size, long long *ts, struct obs_source_audio *audio, bool *got_output); diff --git a/plugins/win-dshow/win-dshow.cpp b/plugins/win-dshow/win-dshow.cpp index 344745de0..ee820d6de 100644 --- a/plugins/win-dshow/win-dshow.cpp +++ b/plugins/win-dshow/win-dshow.cpp @@ -116,6 +116,7 @@ public: inline ~Decoder() {ffmpeg_decode_free(&decode);} inline operator ffmpeg_decode*() {return &decode;} + inline ffmpeg_decode *operator->() {return &decode;} }; class CriticalSection { @@ -507,10 +508,18 @@ void DShowInput::OnEncodedAudioData(enum AVCodecID id, blog(LOG_WARNING, "Could not initialize audio decoder"); return; } + + if (videoConfig.name.find(L"C875") != std::string::npos || + videoConfig.name.find(L"C835") != std::string::npos) { + audio_decoder->fix_braindead_lgp_audio_packet_stupidity + = true; + blog(LOG_INFO, "Oh great, an LGP was detected. " + "How wonderful. I'm just ecstatic."); + } } bool got_output; - int len = ffmpeg_decode_audio(audio_decoder, data, size, + int len = ffmpeg_decode_audio(audio_decoder, data, size, &ts, &audio, &got_output); if (len < 0) { blog(LOG_WARNING, "Error decoding audio");