blob: bdbdaa349bbb5662a04cbe4935b4832df0a9bac9 [file] [log] [blame]
// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
//
// Defines the video sink filter used to obtain raw frames from user input
// devices available via DirectShow. Based on WebRTC's CaptureInputPin and
// CaptureSinkFilter.
#ifndef WEBMLIVE_ENCODER_WIN_VIDEO_SINK_FILTER_H_
#define WEBMLIVE_ENCODER_WIN_VIDEO_SINK_FILTER_H_
#include <memory>
// Wrap include of streams.h with include guard used in the file: including the
// file twice results in the output "STREAMS.H included TWICE" for debug
// builds.
#ifndef __STREAMS__
#pragma warning(push)
#pragma warning(disable:4005)
// Disable C4005 via pragma
// Pragma required because streams.h includes intsafe.h, which defines
// INTSAFE_E_ARITHMETIC_OVERFLOW without an ifndef check, resulting in a
// warning that breaks our build when compiling with warnings-as-errors flag
// enabled.
#include "baseclasses/streams.h"
#pragma warning(pop)
#endif // __STREAMS__
#include "encoder/basictypes.h"
#include "encoder/encoder_base.h"
#include "encoder/video_encoder.h"
#include "encoder/webm_encoder.h"
namespace webmlive {
// Forward declare |VideoSinkFilter| for use in |VideoSinkPin|.
class VideoSinkFilter;
// Pin class used by |VideoSinkFilter|. Accepts only I420 video input.
class VideoSinkPin : public CBaseInputPin {
public:
// Constructs CBaseInputPin and returns result via |ptr_result|. Returns
// S_OK when successful.
VideoSinkPin(TCHAR* ptr_object_name,
VideoSinkFilter* ptr_filter,
CCritSec* ptr_filter_lock,
HRESULT* ptr_result,
LPCWSTR ptr_pin_name);
virtual ~VideoSinkPin();
//
// CBasePin methods
//
// Stores preferred media type for |type_index| in |ptr_media_type|. Supports
// only a single type, I420.
// Return values:
// S_OK - success, |type_index| in range and |ptr_media_type| written.
// VFW_S_NO_MORE_ITEMS - |type_index| != 0.
// E_OUTOFMEMORY - could not allocate format buffer.
virtual HRESULT GetMediaType(int32 type_index, CMediaType* ptr_media_type);
// Checks if AM_MEDIA_TYPE stored in CMediaType pointer is acceptable.
// Supports only MEDIASUBTYPE_I420 wrapped in VIDEOINFOHEADER or
// VIDEOINFOHEADER2 structures.
// Return values:
// S_OK - |ptr_media_type| is supported.
// E_INVALIDARG - NULL |ptr_media_type|.
// VFW_E_TYPE_NOT_ACCEPTED - |ptr_media_type| is not supported.
virtual HRESULT CheckMediaType(const CMediaType* ptr_media_type);
//
// IMemInputPin method(s).
//
// Receives video buffers from the upstream filter and passes them to
// |VideoSinkFilter::OnFrameReceived|.
// Returns S_OK, or the HRESULT error value returned CBaseInputPin::Receive
// if it fails.
virtual HRESULT STDMETHODCALLTYPE Receive(IMediaSample* ptr_sample);
private:
// Copies |actual_config_| to |ptr_config| and returns S_OK. Returns
// E_POINTER when |ptr_config| is NULL.
HRESULT config(VideoConfig* ptr_config) const;
// Resets |actual_config_| and copies |config| values to |requested_config_|,
// then returns S_OK.
HRESULT set_config(const VideoConfig& config);
// Returns true when |media_sub_type| is an acceptable video format.
bool AcceptableSubType(const GUID& media_sub_type);
// Filter user's requested video config.
VideoConfig requested_config_;
// Actual video config (from upstream filter).
VideoConfig actual_config_;
WEBMLIVE_DISALLOW_COPY_AND_ASSIGN(VideoSinkPin);
// |VideoSinkFilter| requires access to private member |actual_config_|, and
// private methods |config| and |set_config| for configuration retrieval and
// control.
friend class VideoSinkFilter;
};
// Video sink filter class. Receives I420 video frames from upstream
// DirectShow filter via |VideoSinkPin|.
class VideoSinkFilter : public CBaseFilter {
public:
// Stores |ptr_frame_callback|, constructs CBaseFilter and |VideoSinkPin, and
// returns result via |ptr_result|.
// Return values:
// S_OK - success.
// E_INVALIDARG - |ptr_Frame_callback| is NULL.
// E_OUTOFMEMORY - cannot construct |sink_pin_|.
VideoSinkFilter(const TCHAR* ptr_filter_name,
LPUNKNOWN ptr_iunknown,
VideoFrameCallbackInterface* ptr_frame_callback,
HRESULT* ptr_result);
virtual ~VideoSinkFilter();
// Copies actual video configuration to |ptr_config| and returns S_OK.
HRESULT config(VideoConfig* ptr_config) const;
// Sets actual requested video configuration and returns S_OK.
HRESULT set_config(const VideoConfig& config);
// IUnknown
DECLARE_IUNKNOWN;
// CBaseFilter methods
virtual int GetPinCount() { return 1; }
// Returns the pin at |index|, or NULL. The value of |index| must be 0.
virtual CBasePin* GetPin(int index);
private:
// Copes video frame from |ptr_sample| to |frame_|, and passes |frame_| to
// |VideoFrameCallbackInterface::OnVideoFrameReceived| for processing.
// Returns S_OK when successful.
HRESULT OnFrameReceived(IMediaSample* ptr_sample);
mutable CCritSec filter_lock_;
VideoFrame frame_;
std::unique_ptr<VideoSinkPin> sink_pin_;
VideoFrameCallbackInterface* ptr_frame_callback_;
WEBMLIVE_DISALLOW_COPY_AND_ASSIGN(VideoSinkFilter);
// |VideoSinkPin| requires access to private member |filter_lock_|, and
// private method |OnFrameReceived| to lock the filter and safely deliver
// video frame buffers.
friend class VideoSinkPin;
};
} // namespace webmlive
#endif // WEBMLIVE_ENCODER_WIN_VIDEO_SINK_FILTER_H_