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