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 |