| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // | 4 // |
| 5 // Decodes H.264 Annex B streams using the Media Foundation H.264 decoder as | 5 // MFT H.264 decoder. |
| 6 // a standalone Media Foundation Transform (MFT). | |
| 7 // Note: A single MftH264Decoder instance is only for 1 H.264 video stream only. | |
| 8 // Inputting streams consisting of more than 1 video to a single instance | |
| 9 // may result in undefined behavior. | |
| 10 | 6 |
| 11 #ifndef MEDIA_MF_MFT_H264_DECODER_H_ | 7 #ifndef MEDIA_MF_MFT_H264_DECODER_H_ |
| 12 #define MEDIA_MF_MFT_H264_DECODER_H_ | 8 #define MEDIA_MF_MFT_H264_DECODER_H_ |
| 13 | 9 |
| 14 #include <string> | 10 #include "build/build_config.h" // For OS_WIN. |
| 15 | 11 |
| 12 #if defined(OS_WIN) |
| 13 |
| 14 #include <deque> |
| 15 |
| 16 #include <d3d9.h> |
| 17 #include <dxva2api.h> |
| 16 #include <mfidl.h> | 18 #include <mfidl.h> |
| 17 | 19 |
| 18 #include "base/basictypes.h" | |
| 19 #include "base/callback.h" | |
| 20 #include "base/gtest_prod_util.h" | 20 #include "base/gtest_prod_util.h" |
| 21 #include "base/scoped_ptr.h" | 21 #include "base/scoped_comptr_win.h" |
| 22 #include "media/filters/video_decode_engine.h" |
| 22 | 23 |
| 23 struct IDirect3DDeviceManager9; | 24 class MessageLoop; |
| 24 struct IMFTransform; | |
| 25 | 25 |
| 26 namespace media { | 26 namespace media { |
| 27 | 27 |
| 28 class DataBuffer; | 28 class MftH264Decoder : public media::VideoDecodeEngine { |
| 29 class VideoFrame; | |
| 30 | |
| 31 // A decoder that takes samples of Annex B streams then outputs decoded frames. | |
| 32 class MftH264Decoder : public base::RefCountedThreadSafe<MftH264Decoder> { | |
| 33 public: | 29 public: |
| 34 enum Error { | 30 typedef enum { |
| 35 kResetOutputStreamFailed = 0, | 31 kUninitialized, // un-initialized. |
| 36 kNoMoreOutput, | 32 kNormal, // normal playing state. |
| 37 kUnspecifiedError, | 33 kFlushing, // upon received Flush(), before FlushDone() |
| 38 kNoMemory, | 34 kEosDrain, // upon input EOS received. |
| 39 kOutputSampleError | 35 kStopped, // upon output EOS received. |
| 40 }; | 36 } State; |
| 41 typedef Callback1<scoped_refptr<DataBuffer>*>::Type | |
| 42 ReadInputCallback; | |
| 43 typedef Callback1<scoped_refptr<VideoFrame> >::Type OutputReadyCallback; | |
| 44 typedef Callback1<Error>::Type OutputErrorCallback; | |
| 45 | 37 |
| 46 explicit MftH264Decoder(bool use_dxva); | 38 explicit MftH264Decoder(bool use_dxva); |
| 47 ~MftH264Decoder(); | 39 ~MftH264Decoder(); |
| 40 virtual void Initialize(MessageLoop* message_loop, |
| 41 media::VideoDecodeEngine::EventHandler* event_handler, |
| 42 const VideoCodecConfig& config); |
| 43 virtual void Uninitialize(); |
| 44 virtual void Flush(); |
| 45 virtual void Seek(); |
| 46 virtual void EmptyThisBuffer(scoped_refptr<Buffer> buffer); |
| 47 virtual void FillThisBuffer(scoped_refptr<VideoFrame> frame); |
| 48 | 48 |
| 49 // Initializes the decoder. |dev_manager| is not required if the decoder does | |
| 50 // not use DXVA. | |
| 51 // If the other arguments are not known, leave them as 0. They can be | |
| 52 // provided to the decoder to try to avoid an initial output format change, | |
| 53 // but it is not necessary to have them. | |
| 54 // The object takes ownership of the callbacks. However, the caller must | |
| 55 // make sure the objects associated with the callbacks outlives the time | |
| 56 // when GetOutput() will be called. | |
| 57 bool Init(IDirect3DDeviceManager9* dev_manager, | |
| 58 int frame_rate_num, int frame_rate_denom, | |
| 59 int width, int height, | |
| 60 int aspect_num, int aspect_denom, | |
| 61 ReadInputCallback* read_input_cb, | |
| 62 OutputReadyCallback* output_avail_cb, | |
| 63 OutputErrorCallback* output_error_cb); | |
| 64 | |
| 65 // Tries to get an output sample from the decoder, and if successful, calls | |
| 66 // the callback with the sample, or status of the decoder if an error | |
| 67 // occurred. | |
| 68 void GetOutput(); | |
| 69 bool Flush(); | |
| 70 | |
| 71 bool initialized() const { return initialized_; } | |
| 72 bool use_dxva() const { return use_dxva_; } | 49 bool use_dxva() const { return use_dxva_; } |
| 73 bool drain_message_sent() const { return drain_message_sent_; } | 50 State state() const { return state_; } |
| 74 int in_buffer_size() const { return in_buffer_size_; } | |
| 75 int out_buffer_size() const { return out_buffer_size_; } | |
| 76 int frames_read() const { return frames_read_; } | |
| 77 int frames_decoded() const { return frames_decoded_; } | |
| 78 int width() const { return width_; } | |
| 79 int height() const { return height_; } | |
| 80 | 51 |
| 81 private: | 52 private: |
| 82 friend class MftH264DecoderTest; | 53 friend class MftH264DecoderTest; |
| 83 FRIEND_TEST_ALL_PREFIXES(MftH264DecoderTest, | 54 FRIEND_TEST_ALL_PREFIXES(MftH264DecoderTest, LibraryInit); |
| 84 SendDrainMessageBeforeInitDeathTest); | |
| 85 FRIEND_TEST_ALL_PREFIXES(MftH264DecoderTest, SendDrainMessageAtInit); | |
| 86 FRIEND_TEST_ALL_PREFIXES(MftH264DecoderTest, DrainOnEndOfInputStream); | |
| 87 FRIEND_TEST_ALL_PREFIXES(MftH264DecoderTest, NoOutputOnGarbageInput); | |
| 88 | 55 |
| 89 bool InitComMfLibraries(); | 56 // TODO(jiesun): Find a way to move all these to GpuVideoService.. |
| 90 bool InitDecoder(IDirect3DDeviceManager9* dev_manager, | 57 static bool StartupComLibraries(); |
| 91 int frame_rate_num, int frame_rate_denom, | 58 static void ShutdownComLibraries(); |
| 92 int width, int height, | 59 bool CreateD3DDevManager(); |
| 93 int aspect_num, int aspect_denom); | 60 |
| 94 bool SetDecoderD3d9Manager(IDirect3DDeviceManager9* dev_manager); | 61 bool InitInternal(); |
| 95 bool SetDecoderMediaTypes(int frame_rate_num, int frame_rate_denom, | 62 bool InitDecoder(); |
| 96 int width, int height, | 63 bool CheckDecoderDxvaSupport(); |
| 97 int aspect_num, int aspect_denom); | 64 bool SetDecoderMediaTypes(); |
| 98 bool SetDecoderInputMediaType(int frame_rate_num, int frame_rate_denom, | 65 bool SetDecoderInputMediaType(); |
| 99 int width, int height, | |
| 100 int aspect_num, int aspect_denom); | |
| 101 bool SetDecoderOutputMediaType(const GUID subtype); | 66 bool SetDecoderOutputMediaType(const GUID subtype); |
| 102 bool SendStartMessage(); | 67 bool SendMFTMessage(MFT_MESSAGE_TYPE msg); |
| 103 bool GetStreamsInfoAndBufferReqs(); | 68 bool GetStreamsInfoAndBufferReqs(); |
| 104 bool ReadInput(); | |
| 105 | 69 |
| 106 // Sends an Annex B stream to the decoder. The times here should be given | 70 bool DoDecode(); |
| 107 // in 100ns units. This creates a IMFSample, copies the stream over to the | |
| 108 // sample, and sends the sample to the decoder. | |
| 109 // Returns: true if the sample was sent successfully. | |
| 110 bool SendInput(const uint8* data, int size, int64 timestamp, int64 duration); | |
| 111 | 71 |
| 112 bool SendEndOfStreamMessage(); | |
| 113 | 72 |
| 114 // Sends a drain message to the decoder to indicate no more input will be | 73 bool use_dxva_; |
| 115 // sent. SendInput() should not be called after calling this method. | |
| 116 // Returns: true if the drain message was sent successfully. | |
| 117 bool SendDrainMessage(); | |
| 118 | 74 |
| 119 // |output_error_callback_| should stop the message loop. | 75 ScopedComPtr<IDirect3D9> d3d9_; |
| 120 scoped_ptr<ReadInputCallback> read_input_callback_; | 76 ScopedComPtr<IDirect3DDevice9> device_; |
| 121 scoped_ptr<OutputReadyCallback> output_avail_callback_; | 77 ScopedComPtr<IDirect3DDeviceManager9> device_manager_; |
| 122 scoped_ptr<OutputErrorCallback> output_error_callback_; | 78 HWND device_window_; |
| 123 IMFTransform* decoder_; | 79 ScopedComPtr<IMFTransform> decoder_; |
| 124 bool initialized_; | |
| 125 bool use_dxva_; | |
| 126 bool drain_message_sent_; | |
| 127 bool next_frame_discontinuous_; | |
| 128 | 80 |
| 129 // Minimum input and output buffer sizes/alignment required by the decoder. | 81 MFT_INPUT_STREAM_INFO input_stream_info_; |
| 130 // If |buffer_alignment_| is zero, then the buffer needs not be aligned. | 82 MFT_OUTPUT_STREAM_INFO output_stream_info_; |
| 131 int in_buffer_size_; | 83 |
| 132 int in_buffer_alignment_; | 84 State state_; |
| 133 int out_buffer_size_; | 85 |
| 134 int out_buffer_alignment_; | 86 VideoDecodeEngine::EventHandler* event_handler_; |
| 135 int frames_read_; | 87 VideoCodecConfig config_; |
| 136 int frames_decoded_; | 88 VideoCodecInfo info_; |
| 137 int width_; | |
| 138 int height_; | |
| 139 int stride_; | |
| 140 const GUID output_format_; | |
| 141 | 89 |
| 142 DISALLOW_COPY_AND_ASSIGN(MftH264Decoder); | 90 DISALLOW_COPY_AND_ASSIGN(MftH264Decoder); |
| 143 }; | 91 }; |
| 144 | 92 |
| 145 } // namespace media | 93 } // namespace media |
| 146 | 94 |
| 95 #endif // defined(OS_WIN) |
| 96 |
| 147 #endif // MEDIA_MF_MFT_H264_DECODER_H_ | 97 #endif // MEDIA_MF_MFT_H264_DECODER_H_ |
| OLD | NEW |