Use the preferred capture format on windows.
The existing windows dshow capture code was ignoring the requested capture format when enumerating preferred formats. This CL changes the behavior to move the requested format to the start of the preferred list. This should fix an issue causing MJPEG to be not selected on certain devices because other formats were preferred, resulting in reduced framerates for HD capture (USB 2.0 throughput isn't high enough to support capturing 30fps 720p I420 data, and many cameras, even internal, are on the USB 2.0 bus). Note that Chromium has yet a different implementation, which is if MJPEG is selected, it claims to *only* support MJPEG and no other formats. This solution seems more correct; if, for some reason, MJPEG was listed as supported but isn't asked of the pin, this code will still produce some output, just possibly at a lower framerate or resolution. Bug: None Change-Id: Id86f345936f6f32e08beec02925e41056c87a544 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/130843 Commit-Queue: Tommi <tommi@webrtc.org> Reviewed-by: Tommi <tommi@webrtc.org> Cr-Commit-Position: refs/heads/master@{#27412}
This commit is contained in:
parent
2cc368fd7a
commit
a64f397397
@ -236,7 +236,27 @@ bool TranslateMediaTypeToVideoCaptureCapability(
|
||||
class MediaTypesEnum : public IEnumMediaTypes {
|
||||
public:
|
||||
MediaTypesEnum(const VideoCaptureCapability& capability)
|
||||
: capability_(capability) {}
|
||||
: capability_(capability),
|
||||
format_preference_order_(
|
||||
{// Default preferences, sorted by cost-to-convert-to-i420.
|
||||
VideoType::kI420, VideoType::kYUY2, VideoType::kRGB24,
|
||||
VideoType::kUYVY, VideoType::kMJPEG}) {
|
||||
// Use the preferred video type, if supported.
|
||||
auto it = std::find(format_preference_order_.begin(),
|
||||
format_preference_order_.end(), capability_.videoType);
|
||||
if (it != format_preference_order_.end()) {
|
||||
RTC_LOG(LS_INFO) << "Selected video type: " << *it;
|
||||
// Move it to the front of the list, if it isn't already there.
|
||||
if (it != format_preference_order_.begin()) {
|
||||
format_preference_order_.splice(format_preference_order_.begin(),
|
||||
format_preference_order_, it,
|
||||
std::next(it));
|
||||
}
|
||||
} else {
|
||||
RTC_LOG(LS_WARNING) << "Unsupported video type: " << *it
|
||||
<< ", using default preference list.";
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~MediaTypesEnum() {}
|
||||
@ -264,10 +284,9 @@ class MediaTypesEnum : public IEnumMediaTypes {
|
||||
if (fetched)
|
||||
*fetched = 0;
|
||||
|
||||
// Note, must match switch statement below.
|
||||
constexpr int kNumTypes = 5;
|
||||
|
||||
for (ULONG i = 0; i < count && pos_ < kNumTypes; ++i) {
|
||||
for (ULONG i = 0;
|
||||
i < count && pos_ < static_cast<int>(format_preference_order_.size());
|
||||
++i) {
|
||||
AM_MEDIA_TYPE* media_type = reinterpret_cast<AM_MEDIA_TYPE*>(
|
||||
CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE)));
|
||||
ZeroMemory(media_type, sizeof(*media_type));
|
||||
@ -289,39 +308,9 @@ class MediaTypesEnum : public IEnumMediaTypes {
|
||||
media_type->formattype = FORMAT_VideoInfo;
|
||||
media_type->bTemporalCompression = FALSE;
|
||||
|
||||
switch (pos_++) {
|
||||
case 0:
|
||||
// Note: The previous implementation had a bug that caused this
|
||||
// format to always be omitted. Perhaps including it now will have
|
||||
// a sideffect.
|
||||
vih->bmiHeader.biCompression = MAKEFOURCC('I', '4', '2', '0');
|
||||
vih->bmiHeader.biBitCount = 12; // bit per pixel
|
||||
media_type->subtype = MEDIASUBTYPE_I420;
|
||||
break;
|
||||
case 1:
|
||||
vih->bmiHeader.biCompression = MAKEFOURCC('Y', 'U', 'Y', '2');
|
||||
vih->bmiHeader.biBitCount = 16; // bit per pixel
|
||||
media_type->subtype = MEDIASUBTYPE_YUY2;
|
||||
break;
|
||||
case 2:
|
||||
vih->bmiHeader.biCompression = BI_RGB;
|
||||
vih->bmiHeader.biBitCount = 24; // bit per pixel
|
||||
media_type->subtype = MEDIASUBTYPE_RGB24;
|
||||
break;
|
||||
case 3:
|
||||
vih->bmiHeader.biCompression = MAKEFOURCC('U', 'Y', 'V', 'Y');
|
||||
vih->bmiHeader.biBitCount = 16; // bit per pixel
|
||||
media_type->subtype = MEDIASUBTYPE_UYVY;
|
||||
break;
|
||||
case 4:
|
||||
vih->bmiHeader.biCompression = MAKEFOURCC('M', 'J', 'P', 'G');
|
||||
vih->bmiHeader.biBitCount = 12; // bit per pixel
|
||||
media_type->subtype = MEDIASUBTYPE_MJPG;
|
||||
break;
|
||||
default:
|
||||
RTC_NOTREACHED();
|
||||
break;
|
||||
}
|
||||
// Set format information.
|
||||
auto format_it = std::next(format_preference_order_.begin(), pos_++);
|
||||
SetMediaInfoFromVideoType(*format_it, &vih->bmiHeader, media_type);
|
||||
|
||||
vih->bmiHeader.biWidth = capability_.width;
|
||||
vih->bmiHeader.biHeight = capability_.height;
|
||||
@ -335,8 +324,42 @@ class MediaTypesEnum : public IEnumMediaTypes {
|
||||
if (fetched)
|
||||
++(*fetched);
|
||||
}
|
||||
RTC_DCHECK(pos_ <= kNumTypes);
|
||||
return pos_ == kNumTypes ? S_FALSE : S_OK;
|
||||
return pos_ == static_cast<int>(format_preference_order_.size()) ? S_FALSE
|
||||
: S_OK;
|
||||
}
|
||||
|
||||
static void SetMediaInfoFromVideoType(VideoType video_type,
|
||||
BITMAPINFOHEADER* bitmap_header,
|
||||
AM_MEDIA_TYPE* media_type) {
|
||||
switch (video_type) {
|
||||
case VideoType::kI420:
|
||||
bitmap_header->biCompression = MAKEFOURCC('I', '4', '2', '0');
|
||||
bitmap_header->biBitCount = 12; // bit per pixel
|
||||
media_type->subtype = MEDIASUBTYPE_I420;
|
||||
break;
|
||||
case VideoType::kYUY2:
|
||||
bitmap_header->biCompression = MAKEFOURCC('Y', 'U', 'Y', '2');
|
||||
bitmap_header->biBitCount = 16; // bit per pixel
|
||||
media_type->subtype = MEDIASUBTYPE_YUY2;
|
||||
break;
|
||||
case VideoType::kRGB24:
|
||||
bitmap_header->biCompression = BI_RGB;
|
||||
bitmap_header->biBitCount = 24; // bit per pixel
|
||||
media_type->subtype = MEDIASUBTYPE_RGB24;
|
||||
break;
|
||||
case VideoType::kUYVY:
|
||||
bitmap_header->biCompression = MAKEFOURCC('U', 'Y', 'V', 'Y');
|
||||
bitmap_header->biBitCount = 16; // bit per pixel
|
||||
media_type->subtype = MEDIASUBTYPE_UYVY;
|
||||
break;
|
||||
case VideoType::kMJPEG:
|
||||
bitmap_header->biCompression = MAKEFOURCC('M', 'J', 'P', 'G');
|
||||
bitmap_header->biBitCount = 12; // bit per pixel
|
||||
media_type->subtype = MEDIASUBTYPE_MJPG;
|
||||
break;
|
||||
default:
|
||||
RTC_NOTREACHED();
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHOD(Skip)(ULONG count) {
|
||||
@ -351,6 +374,7 @@ class MediaTypesEnum : public IEnumMediaTypes {
|
||||
|
||||
int pos_ = 0;
|
||||
const VideoCaptureCapability capability_;
|
||||
std::list<VideoType> format_preference_order_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user