Updating XTBs based on .GRDs from branch master
[chromium-blink-merge.git] / media / capture / video / win / sink_input_pin_win.cc
blob240ed9cfa7d0cdfca97bd40f12f4d9dfe4f674e2
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/capture/video/win/sink_input_pin_win.h"
7 #include <cstring>
9 // Avoid including strsafe.h via dshow as it will cause build warnings.
10 #define NO_DSHOW_STRSAFE
11 #include <dshow.h>
13 #include "base/logging.h"
15 namespace media {
17 const REFERENCE_TIME kSecondsToReferenceTime = 10000000;
19 static DWORD GetArea(const BITMAPINFOHEADER& info_header) {
20 return info_header.biWidth * info_header.biHeight;
23 SinkInputPin::SinkInputPin(IBaseFilter* filter, SinkFilterObserver* observer)
24 : PinBase(filter), requested_frame_rate_(0), observer_(observer) {
27 void SinkInputPin::SetRequestedMediaFormat(
28 VideoCapturePixelFormat pixel_format,
29 float frame_rate,
30 const BITMAPINFOHEADER& info_header) {
31 requested_pixel_format_ = pixel_format;
32 requested_frame_rate_ = frame_rate;
33 requested_info_header_ = info_header;
34 resulting_format_.frame_size.SetSize(0, 0);
35 resulting_format_.frame_rate = 0;
36 resulting_format_.pixel_format = VIDEO_CAPTURE_PIXEL_FORMAT_UNKNOWN;
39 const VideoCaptureFormat& SinkInputPin::ResultingFormat() {
40 return resulting_format_;
43 bool SinkInputPin::IsMediaTypeValid(const AM_MEDIA_TYPE* media_type) {
44 GUID type = media_type->majortype;
45 if (type != MEDIATYPE_Video)
46 return false;
48 GUID format_type = media_type->formattype;
49 if (format_type != FORMAT_VideoInfo)
50 return false;
52 // Check for the sub types we support.
53 GUID sub_type = media_type->subtype;
54 VIDEOINFOHEADER* pvi =
55 reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat);
56 if (pvi == NULL)
57 return false;
59 // Store the incoming width and height.
60 resulting_format_.frame_size.SetSize(pvi->bmiHeader.biWidth,
61 abs(pvi->bmiHeader.biHeight));
62 if (pvi->AvgTimePerFrame > 0) {
63 resulting_format_.frame_rate =
64 static_cast<int>(kSecondsToReferenceTime / pvi->AvgTimePerFrame);
65 } else {
66 resulting_format_.frame_rate = requested_frame_rate_;
68 if (sub_type == kMediaSubTypeI420 &&
69 pvi->bmiHeader.biCompression == MAKEFOURCC('I', '4', '2', '0')) {
70 resulting_format_.pixel_format = VIDEO_CAPTURE_PIXEL_FORMAT_I420;
71 return true;
73 if (sub_type == MEDIASUBTYPE_YUY2 &&
74 pvi->bmiHeader.biCompression == MAKEFOURCC('Y', 'U', 'Y', '2')) {
75 resulting_format_.pixel_format = VIDEO_CAPTURE_PIXEL_FORMAT_YUY2;
76 return true;
78 if (sub_type == MEDIASUBTYPE_MJPG &&
79 pvi->bmiHeader.biCompression == MAKEFOURCC('M', 'J', 'P', 'G')) {
80 resulting_format_.pixel_format = VIDEO_CAPTURE_PIXEL_FORMAT_MJPEG;
81 return true;
83 if (sub_type == MEDIASUBTYPE_RGB24 &&
84 pvi->bmiHeader.biCompression == BI_RGB) {
85 resulting_format_.pixel_format = VIDEO_CAPTURE_PIXEL_FORMAT_RGB24;
86 return true;
88 if (sub_type == MEDIASUBTYPE_RGB32 &&
89 pvi->bmiHeader.biCompression == BI_RGB) {
90 resulting_format_.pixel_format = VIDEO_CAPTURE_PIXEL_FORMAT_RGB32;
91 return true;
93 return false;
96 bool SinkInputPin::GetValidMediaType(int index, AM_MEDIA_TYPE* media_type) {
97 if (media_type->cbFormat < sizeof(VIDEOINFOHEADER))
98 return false;
100 VIDEOINFOHEADER* pvi =
101 reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat);
103 ZeroMemory(pvi, sizeof(VIDEOINFOHEADER));
104 pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
105 pvi->bmiHeader.biPlanes = 1;
106 pvi->bmiHeader.biClrImportant = 0;
107 pvi->bmiHeader.biClrUsed = 0;
108 if (requested_frame_rate_ > 0) {
109 pvi->AvgTimePerFrame = kSecondsToReferenceTime / requested_frame_rate_;
112 media_type->majortype = MEDIATYPE_Video;
113 media_type->formattype = FORMAT_VideoInfo;
114 media_type->bTemporalCompression = FALSE;
116 if (requested_pixel_format_ == VIDEO_CAPTURE_PIXEL_FORMAT_MJPEG) {
117 // If the requested pixel format is MJPEG, accept only MJPEG.
118 // This is ok since the capabilities of the capturer have been
119 // enumerated and we know that it is supported.
120 if (index != 0)
121 return false;
123 pvi->bmiHeader = requested_info_header_;
124 return true;
127 switch (index) {
128 case 0: {
129 pvi->bmiHeader.biCompression = MAKEFOURCC('I', '4', '2', '0');
130 pvi->bmiHeader.biBitCount = 12; // bit per pixel
131 pvi->bmiHeader.biWidth = requested_info_header_.biWidth;
132 pvi->bmiHeader.biHeight = requested_info_header_.biHeight;
133 pvi->bmiHeader.biSizeImage = GetArea(requested_info_header_) * 3 / 2;
134 media_type->subtype = kMediaSubTypeI420;
135 break;
137 case 1: {
138 pvi->bmiHeader.biCompression = MAKEFOURCC('Y', 'U', 'Y', '2');
139 pvi->bmiHeader.biBitCount = 16;
140 pvi->bmiHeader.biWidth = requested_info_header_.biWidth;
141 pvi->bmiHeader.biHeight = requested_info_header_.biHeight;
142 pvi->bmiHeader.biSizeImage = GetArea(requested_info_header_) * 2;
143 media_type->subtype = MEDIASUBTYPE_YUY2;
144 break;
146 case 2: {
147 pvi->bmiHeader.biCompression = BI_RGB;
148 pvi->bmiHeader.biBitCount = 24;
149 pvi->bmiHeader.biWidth = requested_info_header_.biWidth;
150 pvi->bmiHeader.biHeight = requested_info_header_.biHeight;
151 pvi->bmiHeader.biSizeImage = GetArea(requested_info_header_) * 3;
152 media_type->subtype = MEDIASUBTYPE_RGB24;
153 break;
155 case 3: {
156 pvi->bmiHeader.biCompression = BI_RGB;
157 pvi->bmiHeader.biBitCount = 32;
158 pvi->bmiHeader.biWidth = requested_info_header_.biWidth;
159 pvi->bmiHeader.biHeight = requested_info_header_.biHeight;
160 pvi->bmiHeader.biSizeImage = GetArea(requested_info_header_) * 4;
161 media_type->subtype = MEDIASUBTYPE_RGB32;
162 break;
164 default:
165 return false;
168 media_type->bFixedSizeSamples = TRUE;
169 media_type->lSampleSize = pvi->bmiHeader.biSizeImage;
170 return true;
173 HRESULT SinkInputPin::Receive(IMediaSample* sample) {
174 const int length = sample->GetActualDataLength();
175 uint8* buffer = NULL;
177 if (length <= 0) {
178 DLOG(WARNING) << "Media sample length is 0 or less.";
179 return S_FALSE;
182 if (FAILED(sample->GetPointer(&buffer)))
183 return S_FALSE;
185 observer_->FrameReceived(buffer, length);
186 return S_OK;
189 SinkInputPin::~SinkInputPin() {
192 } // namespace media