Преглед изворни кода

win-dshow: Implement decoding of encoded devices

jp9000 пре 11 година
родитељ
комит
24ae80a481
3 измењених фајлова са 86 додато и 14 уклоњено
  1. 1 4
      plugins/win-dshow/CMakeLists.txt
  2. 1 1
      plugins/win-dshow/libdshowcapture
  3. 84 9
      plugins/win-dshow/win-dshow.cpp

+ 1 - 4
plugins/win-dshow/CMakeLists.txt

@@ -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
plugins/win-dshow/libdshowcapture

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

+ 84 - 9
plugins/win-dshow/win-dshow.cpp

@@ -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);
 }