win-dshow: Implement decoding of encoded devices

master
jp9000 2014-09-12 19:53:59 -07:00
parent 2378ecdbb5
commit 24ae80a481
3 changed files with 86 additions and 14 deletions

View File

@ -23,11 +23,8 @@ set(libdshowcapture_SOURCES
libdshowcapture/source/dshow-demux.cpp
libdshowcapture/source/dshow-enum.cpp
libdshowcapture/source/dshow-formats.cpp
libdshowcapture/source/dshow-hd-pvr1.cpp
libdshowcapture/source/dshow-hd-pvr2.cpp
libdshowcapture/source/dshow-hd-pvr-rocket.cpp
libdshowcapture/source/dshow-media-type.cpp
libdshowcapture/source/dshow-roxio.cpp
libdshowcapture/source/dshow-encoded-device.cpp
libdshowcapture/source/log.cpp)
set(libdshowcapture_HEADERS

@ -1 +1 @@
Subproject commit dc22d04fd7f6b2fdfd2847d7115e66d462c702b7
Subproject commit 584cd0bbb143ddc4326730272b6a79c3276d6660

View File

@ -93,6 +93,9 @@ struct DShowInput {
bool comInitialized;
bool deviceHasAudio;
Decoder audio_decoder;
Decoder video_decoder;
VideoConfig videoConfig;
AudioConfig audioConfig;
@ -111,10 +114,16 @@ struct DShowInput {
av_log_set_callback(ffmpeg_log);
}
void OnEncodedVideoData(enum AVCodecID id,
unsigned char *data, size_t size, long long ts);
void OnEncodedAudioData(enum AVCodecID id,
unsigned char *data, size_t size, long long ts);
void OnVideoData(unsigned char *data, size_t size,
void OnVideoData(const VideoConfig &config,
unsigned char *data, size_t size,
long long startTime, long long endTime);
void OnAudioData(unsigned char *data, size_t size,
void OnAudioData(const AudioConfig &config,
unsigned char *data, size_t size,
long long startTime, long long endTime);
bool UpdateVideoConfig(obs_data_t settings);
@ -192,9 +201,39 @@ static inline audio_format ConvertAudioFormat(AudioFormat format)
}
}
void DShowInput::OnVideoData(unsigned char *data, size_t size,
void DShowInput::OnEncodedVideoData(enum AVCodecID id,
unsigned char *data, size_t size, long long ts)
{
if (!ffmpeg_decode_valid(video_decoder)) {
if (ffmpeg_decode_init(video_decoder, id) < 0) {
blog(LOG_WARNING, "Could not initialize video decoder");
return;
}
}
bool got_output;
int len = ffmpeg_decode_video(video_decoder, data, size, &ts,
&frame, &got_output);
if (len < 0) {
blog(LOG_WARNING, "Error decoding video");
return;
}
if (got_output) {
frame.timestamp = (uint64_t)ts * 100;
blog(LOG_DEBUG, "video ts: %llu", frame.timestamp);
obs_source_output_video(source, &frame);
}
}
void DShowInput::OnVideoData(const VideoConfig &config,
unsigned char *data, size_t size,
long long startTime, long long endTime)
{
if (videoConfig.format == VideoFormat::H264) {
OnEncodedVideoData(AV_CODEC_ID_H264, data, size, startTime);
return;
}
const int cx = videoConfig.cx;
const int cy = videoConfig.cy;
@ -231,11 +270,45 @@ void DShowInput::OnVideoData(unsigned char *data, size_t size,
UNUSED_PARAMETER(size);
}
void DShowInput::OnAudioData(unsigned char *data, size_t size,
void DShowInput::OnEncodedAudioData(enum AVCodecID id,
unsigned char *data, size_t size, long long ts)
{
if (!ffmpeg_decode_valid(audio_decoder)) {
if (ffmpeg_decode_init(audio_decoder, id) < 0) {
blog(LOG_WARNING, "Could not initialize audio decoder");
return;
}
}
bool got_output;
int len = ffmpeg_decode_audio(audio_decoder, data, size,
&audio, &got_output);
if (len < 0) {
blog(LOG_WARNING, "Error decoding audio");
return;
}
if (got_output) {
audio.timestamp = (uint64_t)ts * 100;
//blog(LOG_DEBUG, "audio ts: %llu", audio.timestamp);
obs_source_output_audio(source, &audio);
}
}
void DShowInput::OnAudioData(const AudioConfig &config,
unsigned char *data, size_t size,
long long startTime, long long endTime)
{
if (audio.format == AUDIO_FORMAT_UNKNOWN)
if (config.format == AudioFormat::AAC) {
OnEncodedAudioData(AV_CODEC_ID_AAC, data, size, startTime);
return;
} else if (config.format == AudioFormat::AC3) {
OnEncodedAudioData(AV_CODEC_ID_AC3, data, size, startTime);
return;
} else if (config.format == AudioFormat::MPGA) {
OnEncodedAudioData(AV_CODEC_ID_MP1, data, size, startTime);
return;
}
size_t block_size = get_audio_bytes_per_channel(audio.format) *
get_audio_channels(audio.speakers);
@ -244,10 +317,10 @@ void DShowInput::OnAudioData(unsigned char *data, size_t size,
audio.frames = (uint32_t)(size / block_size);
audio.timestamp = (uint64_t)startTime * 100;
obs_source_output_audio(source, &audio);
if (audio.format != AUDIO_FORMAT_UNKNOWN)
obs_source_output_audio(source, &audio);
UNUSED_PARAMETER(endTime);
UNUSED_PARAMETER(size);
}
static bool DecodeDeviceId(DStr &name, DStr &path, const char *device_id)
@ -507,7 +580,8 @@ bool DShowInput::UpdateVideoConfig(obs_data_t settings)
videoConfig.callback = std::bind(&DShowInput::OnVideoData, this,
placeholders::_1, placeholders::_2,
placeholders::_3, placeholders::_4);
placeholders::_3, placeholders::_4,
placeholders::_5);
if (videoConfig.internalFormat != VideoFormat::MJPEG)
videoConfig.format = videoConfig.internalFormat;
@ -545,7 +619,8 @@ bool DShowInput::UpdateAudioConfig(obs_data_t settings)
audioConfig.callback = std::bind(&DShowInput::OnAudioData, this,
placeholders::_1, placeholders::_2,
placeholders::_3, placeholders::_4);
placeholders::_3, placeholders::_4,
placeholders::_5);
return device.SetAudioConfig(&audioConfig);
}