• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "media/video/capture/win/sink_input_pin_win.h"
6 
7 #include <cstring>
8 
9 // Avoid including strsafe.h via dshow as it will cause build warnings.
10 #define NO_DSHOW_STRSAFE
11 #include <dshow.h>
12 
13 #include "base/logging.h"
14 
15 namespace media {
16 
17 const REFERENCE_TIME kSecondsToReferenceTime = 10000000;
18 
SinkInputPin(IBaseFilter * filter,SinkFilterObserver * observer)19 SinkInputPin::SinkInputPin(IBaseFilter* filter,
20                            SinkFilterObserver* observer)
21     : observer_(observer),
22       PinBase(filter) {
23 }
24 
~SinkInputPin()25 SinkInputPin::~SinkInputPin() {}
26 
GetValidMediaType(int index,AM_MEDIA_TYPE * media_type)27 bool SinkInputPin::GetValidMediaType(int index, AM_MEDIA_TYPE* media_type) {
28   if (media_type->cbFormat < sizeof(VIDEOINFOHEADER))
29     return false;
30 
31   VIDEOINFOHEADER* pvi =
32       reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat);
33 
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;
42   }
43 
44   media_type->majortype = MEDIATYPE_Video;
45   media_type->formattype = FORMAT_VideoInfo;
46   media_type->bTemporalCompression = FALSE;
47 
48   switch (index) {
49     case 0: {
50       pvi->bmiHeader.biCompression = MAKEFOURCC('I', '4', '2', '0');
51       pvi->bmiHeader.biBitCount = 12;  // bit per pixel
52       pvi->bmiHeader.biWidth = requested_format_.frame_size.width();
53       pvi->bmiHeader.biHeight = requested_format_.frame_size.height();
54       pvi->bmiHeader.biSizeImage =
55           requested_format_.frame_size.GetArea() * 3 / 2;
56       media_type->subtype = kMediaSubTypeI420;
57       break;
58     }
59     case 1: {
60       pvi->bmiHeader.biCompression = MAKEFOURCC('Y', 'U', 'Y', '2');
61       pvi->bmiHeader.biBitCount = 16;
62       pvi->bmiHeader.biWidth = requested_format_.frame_size.width();
63       pvi->bmiHeader.biHeight = requested_format_.frame_size.height();
64       pvi->bmiHeader.biSizeImage = requested_format_.frame_size.GetArea() * 2;
65       media_type->subtype = MEDIASUBTYPE_YUY2;
66       break;
67     }
68     case 2: {
69       pvi->bmiHeader.biCompression = BI_RGB;
70       pvi->bmiHeader.biBitCount = 24;
71       pvi->bmiHeader.biWidth = requested_format_.frame_size.width();
72       pvi->bmiHeader.biHeight = requested_format_.frame_size.height();
73       pvi->bmiHeader.biSizeImage = requested_format_.frame_size.GetArea() * 3;
74       media_type->subtype = MEDIASUBTYPE_RGB24;
75       break;
76     }
77     default:
78       return false;
79   }
80 
81   media_type->bFixedSizeSamples = TRUE;
82   media_type->lSampleSize = pvi->bmiHeader.biSizeImage;
83   return true;
84 }
85 
IsMediaTypeValid(const AM_MEDIA_TYPE * media_type)86 bool SinkInputPin::IsMediaTypeValid(const AM_MEDIA_TYPE* media_type) {
87   GUID type = media_type->majortype;
88   if (type != MEDIATYPE_Video)
89     return false;
90 
91   GUID format_type = media_type->formattype;
92   if (format_type != FORMAT_VideoInfo)
93     return false;
94 
95   // Check for the sub types we support.
96   GUID sub_type = media_type->subtype;
97   VIDEOINFOHEADER* pvi =
98       reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat);
99   if (pvi == NULL)
100     return false;
101 
102   // Store the incoming width and height.
103   resulting_format_.frame_size.SetSize(pvi->bmiHeader.biWidth,
104                                        abs(pvi->bmiHeader.biHeight));
105   if (pvi->AvgTimePerFrame > 0) {
106     resulting_format_.frame_rate =
107         static_cast<int>(kSecondsToReferenceTime / pvi->AvgTimePerFrame);
108   } else {
109     resulting_format_.frame_rate = requested_format_.frame_rate;
110   }
111   if (sub_type == kMediaSubTypeI420 &&
112       pvi->bmiHeader.biCompression == MAKEFOURCC('I', '4', '2', '0')) {
113     resulting_format_.pixel_format = PIXEL_FORMAT_I420;
114     return true;  // This format is acceptable.
115   }
116   if (sub_type == MEDIASUBTYPE_YUY2 &&
117       pvi->bmiHeader.biCompression == MAKEFOURCC('Y', 'U', 'Y', '2')) {
118     resulting_format_.pixel_format = PIXEL_FORMAT_YUY2;
119     return true;  // This format is acceptable.
120   }
121   if (sub_type == MEDIASUBTYPE_RGB24 &&
122       pvi->bmiHeader.biCompression == BI_RGB) {
123     resulting_format_.pixel_format = PIXEL_FORMAT_RGB24;
124     return true;  // This format is acceptable.
125   }
126   return false;
127 }
128 
Receive(IMediaSample * sample)129 HRESULT SinkInputPin::Receive(IMediaSample* sample) {
130   const int length = sample->GetActualDataLength();
131   uint8* buffer = NULL;
132   if (FAILED(sample->GetPointer(&buffer)))
133     return S_FALSE;
134 
135   observer_->FrameReceived(buffer, length);
136   return S_OK;
137 }
138 
SetRequestedMediaFormat(const VideoCaptureFormat & format)139 void SinkInputPin::SetRequestedMediaFormat(const VideoCaptureFormat& format) {
140   requested_format_ = format;
141   resulting_format_.frame_size.SetSize(0, 0);
142   resulting_format_.frame_rate = 0;
143   resulting_format_.pixel_format = PIXEL_FORMAT_UNKNOWN;
144 }
145 
ResultingFormat()146 const VideoCaptureFormat& SinkInputPin::ResultingFormat() {
147   return resulting_format_;
148 }
149 
150 }  // namespace media
151