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/video/capture/win/sink_input_pin_win.h"
9 // Avoid including strsafe.h via dshow as it will cause build warnings.
10 #define NO_DSHOW_STRSAFE
13 #include "base/logging.h"
17 const REFERENCE_TIME kSecondsToReferenceTime
= 10000000;
19 SinkInputPin::SinkInputPin(IBaseFilter
* filter
,
20 SinkFilterObserver
* observer
)
21 : observer_(observer
),
25 SinkInputPin::~SinkInputPin() {}
27 bool SinkInputPin::GetValidMediaType(int index
, AM_MEDIA_TYPE
* media_type
) {
28 if (media_type
->cbFormat
< sizeof(VIDEOINFOHEADER
))
31 VIDEOINFOHEADER
* pvi
=
32 reinterpret_cast<VIDEOINFOHEADER
*>(media_type
->pbFormat
);
34 ZeroMemory(pvi
, sizeof(VIDEOINFOHEADER
));
35 pvi
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
36 pvi
->bmiHeader
.biPlanes
= 1;
37 pvi
->bmiHeader
.biClrImportant
= 0;
38 pvi
->bmiHeader
.biClrUsed
= 0;
39 if (requested_format_
.frame_rate
> 0) {
40 pvi
->AvgTimePerFrame
=
41 kSecondsToReferenceTime
/ requested_format_
.frame_rate
;
44 media_type
->majortype
= MEDIATYPE_Video
;
45 media_type
->formattype
= FORMAT_VideoInfo
;
46 media_type
->bTemporalCompression
= FALSE
;
48 if (requested_format_
.pixel_format
== PIXEL_FORMAT_MJPEG
) {
49 // If the requested pixel format is MJPEG, accept only MJPEG.
50 // This is ok since the capabilities of the capturer have been
51 // enumerated and we know that it is supported.
55 pvi
->bmiHeader
.biCompression
= MAKEFOURCC('M', 'J', 'P', 'G');
56 pvi
->bmiHeader
.biBitCount
= 0;
57 pvi
->bmiHeader
.biWidth
= requested_format_
.frame_size
.width();
58 pvi
->bmiHeader
.biHeight
= requested_format_
.frame_size
.height();
59 pvi
->bmiHeader
.biSizeImage
= 0;
60 media_type
->subtype
= MEDIASUBTYPE_MJPG
;
61 media_type
->bFixedSizeSamples
= FALSE
;
62 media_type
->lSampleSize
= pvi
->bmiHeader
.biSizeImage
;
68 pvi
->bmiHeader
.biCompression
= MAKEFOURCC('I', '4', '2', '0');
69 pvi
->bmiHeader
.biBitCount
= 12; // bit per pixel
70 pvi
->bmiHeader
.biWidth
= requested_format_
.frame_size
.width();
71 pvi
->bmiHeader
.biHeight
= requested_format_
.frame_size
.height();
72 pvi
->bmiHeader
.biSizeImage
=
73 requested_format_
.frame_size
.GetArea() * 3 / 2;
74 media_type
->subtype
= kMediaSubTypeI420
;
78 pvi
->bmiHeader
.biCompression
= MAKEFOURCC('Y', 'U', 'Y', '2');
79 pvi
->bmiHeader
.biBitCount
= 16;
80 pvi
->bmiHeader
.biWidth
= requested_format_
.frame_size
.width();
81 pvi
->bmiHeader
.biHeight
= requested_format_
.frame_size
.height();
82 pvi
->bmiHeader
.biSizeImage
= requested_format_
.frame_size
.GetArea() * 2;
83 media_type
->subtype
= MEDIASUBTYPE_YUY2
;
87 pvi
->bmiHeader
.biCompression
= BI_RGB
;
88 pvi
->bmiHeader
.biBitCount
= 24;
89 pvi
->bmiHeader
.biWidth
= requested_format_
.frame_size
.width();
90 pvi
->bmiHeader
.biHeight
= requested_format_
.frame_size
.height();
91 pvi
->bmiHeader
.biSizeImage
= requested_format_
.frame_size
.GetArea() * 3;
92 media_type
->subtype
= MEDIASUBTYPE_RGB24
;
99 media_type
->bFixedSizeSamples
= TRUE
;
100 media_type
->lSampleSize
= pvi
->bmiHeader
.biSizeImage
;
104 bool SinkInputPin::IsMediaTypeValid(const AM_MEDIA_TYPE
* media_type
) {
105 GUID type
= media_type
->majortype
;
106 if (type
!= MEDIATYPE_Video
)
109 GUID format_type
= media_type
->formattype
;
110 if (format_type
!= FORMAT_VideoInfo
)
113 // Check for the sub types we support.
114 GUID sub_type
= media_type
->subtype
;
115 VIDEOINFOHEADER
* pvi
=
116 reinterpret_cast<VIDEOINFOHEADER
*>(media_type
->pbFormat
);
120 // Store the incoming width and height.
121 resulting_format_
.frame_size
.SetSize(pvi
->bmiHeader
.biWidth
,
122 abs(pvi
->bmiHeader
.biHeight
));
123 if (pvi
->AvgTimePerFrame
> 0) {
124 resulting_format_
.frame_rate
=
125 static_cast<int>(kSecondsToReferenceTime
/ pvi
->AvgTimePerFrame
);
127 resulting_format_
.frame_rate
= requested_format_
.frame_rate
;
129 if (sub_type
== kMediaSubTypeI420
&&
130 pvi
->bmiHeader
.biCompression
== MAKEFOURCC('I', '4', '2', '0')) {
131 resulting_format_
.pixel_format
= PIXEL_FORMAT_I420
;
132 return true; // This format is acceptable.
134 if (sub_type
== MEDIASUBTYPE_YUY2
&&
135 pvi
->bmiHeader
.biCompression
== MAKEFOURCC('Y', 'U', 'Y', '2')) {
136 resulting_format_
.pixel_format
= PIXEL_FORMAT_YUY2
;
137 return true; // This format is acceptable.
139 if (sub_type
== MEDIASUBTYPE_MJPG
&&
140 pvi
->bmiHeader
.biCompression
== MAKEFOURCC('M', 'J', 'P', 'G')) {
141 resulting_format_
.pixel_format
= PIXEL_FORMAT_MJPEG
;
142 return true; // This format is acceptable.
144 if (sub_type
== MEDIASUBTYPE_RGB24
&&
145 pvi
->bmiHeader
.biCompression
== BI_RGB
) {
146 resulting_format_
.pixel_format
= PIXEL_FORMAT_RGB24
;
147 return true; // This format is acceptable.
152 HRESULT
SinkInputPin::Receive(IMediaSample
* sample
) {
153 const int length
= sample
->GetActualDataLength();
154 uint8
* buffer
= NULL
;
155 if (FAILED(sample
->GetPointer(&buffer
)))
158 observer_
->FrameReceived(buffer
, length
);
162 void SinkInputPin::SetRequestedMediaFormat(const VideoCaptureFormat
& format
) {
163 requested_format_
= format
;
164 resulting_format_
.frame_size
.SetSize(0, 0);
165 resulting_format_
.frame_rate
= 0;
166 resulting_format_
.pixel_format
= PIXEL_FORMAT_UNKNOWN
;
169 const VideoCaptureFormat
& SinkInputPin::ResultingFormat() {
170 return resulting_format_
;