15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/video/capture/win/sink_input_pin_win.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cstring>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Avoid including strsafe.h via dshow as it will cause build warnings.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NO_DSHOW_STRSAFE
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <dshow.h>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const REFERENCE_TIME kSecondsToReferenceTime = 10000000;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SinkInputPin::SinkInputPin(IBaseFilter* filter,
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           SinkFilterObserver* observer)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : observer_(observer),
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PinBase(filter) {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SinkInputPin::~SinkInputPin() {}
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SinkInputPin::GetValidMediaType(int index, AM_MEDIA_TYPE* media_type) {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (media_type->cbFormat < sizeof(VIDEOINFOHEADER))
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VIDEOINFOHEADER* pvi =
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ZeroMemory(pvi, sizeof(VIDEOINFOHEADER));
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pvi->bmiHeader.biPlanes = 1;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pvi->bmiHeader.biClrImportant = 0;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pvi->bmiHeader.biClrUsed = 0;
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (requested_format_.frame_rate > 0) {
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    pvi->AvgTimePerFrame =
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        kSecondsToReferenceTime / requested_format_.frame_rate;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media_type->majortype = MEDIATYPE_Video;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media_type->formattype = FORMAT_VideoInfo;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media_type->bTemporalCompression = FALSE;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (index) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 0: {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pvi->bmiHeader.biCompression = MAKEFOURCC('I', '4', '2', '0');
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pvi->bmiHeader.biBitCount = 12;  // bit per pixel
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      pvi->bmiHeader.biWidth = requested_format_.frame_size.width();
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      pvi->bmiHeader.biHeight = requested_format_.frame_size.height();
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      pvi->bmiHeader.biSizeImage =
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          requested_format_.frame_size.GetArea() * 3 / 2;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      media_type->subtype = kMediaSubTypeI420;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pvi->bmiHeader.biCompression = MAKEFOURCC('Y', 'U', 'Y', '2');
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pvi->bmiHeader.biBitCount = 16;
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      pvi->bmiHeader.biWidth = requested_format_.frame_size.width();
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      pvi->bmiHeader.biHeight = requested_format_.frame_size.height();
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      pvi->bmiHeader.biSizeImage = requested_format_.frame_size.GetArea() * 2;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      media_type->subtype = MEDIASUBTYPE_YUY2;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2: {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pvi->bmiHeader.biCompression = BI_RGB;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pvi->bmiHeader.biBitCount = 24;
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      pvi->bmiHeader.biWidth = requested_format_.frame_size.width();
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      pvi->bmiHeader.biHeight = requested_format_.frame_size.height();
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      pvi->bmiHeader.biSizeImage = requested_format_.frame_size.GetArea() * 3;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      media_type->subtype = MEDIASUBTYPE_RGB24;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media_type->bFixedSizeSamples = TRUE;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media_type->lSampleSize = pvi->bmiHeader.biSizeImage;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SinkInputPin::IsMediaTypeValid(const AM_MEDIA_TYPE* media_type) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GUID type = media_type->majortype;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type != MEDIATYPE_Video)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GUID format_type = media_type->formattype;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (format_type != FORMAT_VideoInfo)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check for the sub types we support.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GUID sub_type = media_type->subtype;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VIDEOINFOHEADER* pvi =
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pvi == NULL)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Store the incoming width and height.
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  resulting_format_.frame_size.SetSize(pvi->bmiHeader.biWidth,
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                       abs(pvi->bmiHeader.biHeight));
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pvi->AvgTimePerFrame > 0) {
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    resulting_format_.frame_rate =
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<int>(kSecondsToReferenceTime / pvi->AvgTimePerFrame);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    resulting_format_.frame_rate = requested_format_.frame_rate;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sub_type == kMediaSubTypeI420 &&
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pvi->bmiHeader.biCompression == MAKEFOURCC('I', '4', '2', '0')) {
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    resulting_format_.pixel_format = PIXEL_FORMAT_I420;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;  // This format is acceptable.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sub_type == MEDIASUBTYPE_YUY2 &&
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pvi->bmiHeader.biCompression == MAKEFOURCC('Y', 'U', 'Y', '2')) {
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    resulting_format_.pixel_format = PIXEL_FORMAT_YUY2;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;  // This format is acceptable.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sub_type == MEDIASUBTYPE_RGB24 &&
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pvi->bmiHeader.biCompression == BI_RGB) {
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    resulting_format_.pixel_format = PIXEL_FORMAT_RGB24;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;  // This format is acceptable.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT SinkInputPin::Receive(IMediaSample* sample) {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int length = sample->GetActualDataLength();
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* buffer = NULL;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(sample->GetPointer(&buffer)))
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return S_FALSE;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer_->FrameReceived(buffer, length);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return S_OK;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SinkInputPin::SetRequestedMediaFormat(const VideoCaptureFormat& format) {
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  requested_format_ = format;
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  resulting_format_.frame_size.SetSize(0, 0);
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  resulting_format_.frame_rate = 0;
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  resulting_format_.pixel_format = PIXEL_FORMAT_UNKNOWN;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const VideoCaptureFormat& SinkInputPin::ResultingFormat() {
147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return resulting_format_;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
151