Home | History | Annotate | Download | only in win
      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 
     19 SinkInputPin::SinkInputPin(IBaseFilter* filter,
     20                            SinkFilterObserver* observer)
     21     : observer_(observer),
     22       PinBase(filter) {
     23 }
     24 
     25 SinkInputPin::~SinkInputPin() {}
     26 
     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 
     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 
    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 
    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 
    146 const VideoCaptureFormat& SinkInputPin::ResultingFormat() {
    147   return resulting_format_;
    148 }
    149 
    150 }  // namespace media
    151