xref: /haiku/src/kits/media/MediaDecoder.cpp (revision 220d04022750f40f8bac8f01fa551211e28d04f2)
1 /***********************************************************************
2  * AUTHOR: Andrew Bachmann, Marcus Overhagen
3  *   FILE: MediaDecoder.cpp
4  *  DESCR:
5  ***********************************************************************/
6 #include <MediaDecoder.h>
7 #include <DecoderPlugin.h>
8 #include <new>
9 #include "PluginManager.h"
10 #include "debug.h"
11 
12 /*************************************************************
13  * public BMediaDecoder
14  *************************************************************/
15 
16 BMediaDecoder::BMediaDecoder()
17  :	fDecoder(NULL),
18  	fInitStatus(B_NO_INIT)
19 {
20 }
21 
22 
23 BMediaDecoder::BMediaDecoder(const media_format *in_format,
24 							 const void *info,
25 							 size_t info_size)
26  :	fDecoder(NULL),
27  	fInitStatus(B_NO_INIT)
28 {
29 	SetTo(in_format, info, info_size);
30 }
31 
32 
33 BMediaDecoder::BMediaDecoder(const media_codec_info *mci)
34  :	fDecoder(NULL),
35  	fInitStatus(B_NO_INIT)
36 {
37 	SetTo(mci);
38 }
39 
40 
41 /* virtual */
42 BMediaDecoder::~BMediaDecoder()
43 {
44 	gPluginManager.DestroyDecoder(fDecoder);
45 }
46 
47 
48 status_t
49 BMediaDecoder::InitCheck() const
50 {
51 	return fInitStatus;
52 }
53 
54 
55 status_t
56 BMediaDecoder::SetTo(const media_format *in_format,
57 					 const void *info,
58 					 size_t info_size)
59 {
60 	gPluginManager.DestroyDecoder(fDecoder);
61 	fDecoder = NULL;
62 
63 	status_t err = gPluginManager.CreateDecoder(&fDecoder, *in_format);
64 	if (err < B_OK)
65 		goto fail;
66 
67 	err = AttachToDecoder();
68 	if (err < B_OK)
69 		goto fail;
70 
71 	err = SetInputFormat(in_format, info, info_size);
72 	if (err < B_OK)
73 		goto fail;
74 
75 	fInitStatus = B_OK;
76 	return B_OK;
77 
78 fail:
79 	gPluginManager.DestroyDecoder(fDecoder);
80 	fDecoder = NULL;
81 	fInitStatus = B_NO_INIT;
82 	return err;
83 }
84 
85 
86 status_t
87 BMediaDecoder::SetTo(const media_codec_info *mci)
88 {
89 	gPluginManager.DestroyDecoder(fDecoder);
90 	fDecoder = NULL;
91 
92 	status_t err = gPluginManager.CreateDecoder(&fDecoder, *mci);
93 	if (err < B_OK)
94 		goto fail;
95 
96 	err = AttachToDecoder();
97 	if (err < B_OK)
98 		goto fail;
99 
100 	fInitStatus = B_OK;
101 	return B_OK;
102 
103 fail:
104 	gPluginManager.DestroyDecoder(fDecoder);
105 	fDecoder = NULL;
106 	fInitStatus = B_NO_INIT;
107 	return err;
108 }
109 
110 
111 /**	SetInputFormat() sets the input data format to in_format.
112  *	Unlike SetTo(), the SetInputFormat() function does not
113  *	select a codec, so the currently-selected codec will
114  *	continue to be used.  You should only use SetInputFormat()
115  *	to refine the format settings if it will not require the
116  *	use of a different decoder.
117  */
118 
119 status_t
120 BMediaDecoder::SetInputFormat(const media_format *in_format,
121 							  const void *in_info,
122 							  size_t in_size)
123 {
124 	if (!fDecoder)
125 		return B_NO_INIT;
126 
127 	media_format format = *in_format;
128 	return fDecoder->Setup(&format, in_info, in_size);
129 }
130 
131 
132 /**	SetOutputFormat() sets the format the decoder should output.
133  *	On return, the output_format is changed to match the actual
134  *	format that will be output; this can be different if you
135  *	specified any wildcards.
136  */
137 
138 status_t
139 BMediaDecoder::SetOutputFormat(media_format *output_format)
140 {
141 	if (!fDecoder)
142 		return B_NO_INIT;
143 
144 	return fDecoder->NegotiateOutputFormat(output_format);
145 }
146 
147 
148 /**	Decodes a chunk of media data into the output buffer specified
149  *	by out_buffer.  On return, out_frameCount is set to indicate how
150  *	many frames of data were decoded, and out_mh is the header for
151  *	the decoded buffer.  The media_decode_info structure info is used
152  *	on input to specify decoding parameters.
153  *
154  *	The amount of data decoded is part of the format determined by
155  *	SetTo() or SetInputFormat().  For audio, it's the buffer_size.
156  *	For video, it's one frame, which is height*row_bytes.  The data
157  *	to be decoded will be fetched from the source by the decoder
158  *	add-on calling the derived class' GetNextChunk() function.
159  */
160 
161 status_t
162 BMediaDecoder::Decode(void *out_buffer,
163 					  int64 *out_frameCount,
164 					  media_header *out_mh,
165 					  media_decode_info *info)
166 {
167 	if (!fDecoder)
168 		return B_NO_INIT;
169 
170 	return fDecoder->Decode(out_buffer, out_frameCount, out_mh, info);
171 }
172 
173 
174 status_t
175 BMediaDecoder::GetDecoderInfo(media_codec_info *out_info) const
176 {
177 	if (!fDecoder)
178 		return B_NO_INIT;
179 
180 	return gPluginManager.GetDecoderInfo(fDecoder, out_info);
181 }
182 
183 
184 /*************************************************************
185  * protected BMediaDecoder
186  *************************************************************/
187 
188 
189 /*************************************************************
190  * private BMediaDecoder
191  *************************************************************/
192 
193 /*
194 // unimplemented
195 BMediaDecoder::BMediaDecoder(const BMediaDecoder &);
196 BMediaDecoder::BMediaDecoder & operator=(const BMediaDecoder &);
197 */
198 
199 status_t
200 BMediaDecoder::AttachToDecoder()
201 {
202 	class MediaDecoderChunkProvider : public ChunkProvider {
203 	private:
204 		BMediaDecoder * fDecoder;
205 	public:
206 		MediaDecoderChunkProvider(BMediaDecoder * decoder) {
207 			fDecoder = decoder;
208 		}
209 		virtual status_t GetNextChunk(const void **chunkBuffer, size_t *chunkSize,
210 		                              media_header *mediaHeader) {
211 			return fDecoder->GetNextChunk(chunkBuffer, chunkSize, mediaHeader);
212 		}
213 	} * provider = new(std::nothrow) MediaDecoderChunkProvider(this);
214 
215 	if (!provider)
216 		return B_NO_MEMORY;
217 
218 	fDecoder->SetChunkProvider(provider);
219 	return B_OK;
220 }
221 
222 
223 status_t BMediaDecoder::_Reserved_BMediaDecoder_0(int32 arg, ...) { return B_ERROR; }
224 status_t BMediaDecoder::_Reserved_BMediaDecoder_1(int32 arg, ...) { return B_ERROR; }
225 status_t BMediaDecoder::_Reserved_BMediaDecoder_2(int32 arg, ...) { return B_ERROR; }
226 status_t BMediaDecoder::_Reserved_BMediaDecoder_3(int32 arg, ...) { return B_ERROR; }
227 status_t BMediaDecoder::_Reserved_BMediaDecoder_4(int32 arg, ...) { return B_ERROR; }
228 status_t BMediaDecoder::_Reserved_BMediaDecoder_5(int32 arg, ...) { return B_ERROR; }
229 status_t BMediaDecoder::_Reserved_BMediaDecoder_6(int32 arg, ...) { return B_ERROR; }
230 status_t BMediaDecoder::_Reserved_BMediaDecoder_7(int32 arg, ...) { return B_ERROR; }
231 status_t BMediaDecoder::_Reserved_BMediaDecoder_8(int32 arg, ...) { return B_ERROR; }
232 status_t BMediaDecoder::_Reserved_BMediaDecoder_9(int32 arg, ...) { return B_ERROR; }
233 status_t BMediaDecoder::_Reserved_BMediaDecoder_10(int32 arg, ...) { return B_ERROR; }
234 status_t BMediaDecoder::_Reserved_BMediaDecoder_11(int32 arg, ...) { return B_ERROR; }
235 status_t BMediaDecoder::_Reserved_BMediaDecoder_12(int32 arg, ...) { return B_ERROR; }
236 status_t BMediaDecoder::_Reserved_BMediaDecoder_13(int32 arg, ...) { return B_ERROR; }
237 status_t BMediaDecoder::_Reserved_BMediaDecoder_14(int32 arg, ...) { return B_ERROR; }
238 status_t BMediaDecoder::_Reserved_BMediaDecoder_15(int32 arg, ...) { return B_ERROR; }
239 
240 /*************************************************************
241  * public BMediaBufferDecoder
242  *************************************************************/
243 
244 BMediaBufferDecoder::BMediaBufferDecoder()
245  :	BMediaDecoder()
246  ,	fBufferSize(0)
247 {
248 }
249 
250 
251 BMediaBufferDecoder::BMediaBufferDecoder(const media_format *in_format,
252 										 const void *info,
253 										 size_t info_size)
254  :	BMediaDecoder(in_format, info, info_size)
255  ,	fBufferSize(0)
256 {
257 }
258 
259 
260 BMediaBufferDecoder::BMediaBufferDecoder(const media_codec_info *mci)
261  :	BMediaDecoder(mci)
262  ,	fBufferSize(0)
263 {
264 }
265 
266 
267 status_t
268 BMediaBufferDecoder::DecodeBuffer(const void *input_buffer,
269 								  size_t input_size,
270 								  void *out_buffer,
271 								  int64 *out_frameCount,
272 								  media_header *out_mh,
273 								  media_decode_info *info)
274 {
275 	fBuffer = input_buffer;
276 	fBufferSize = input_size;
277 	return Decode(out_buffer, out_frameCount, out_mh,info);
278 }
279 
280 
281 /*************************************************************
282  * protected BMediaBufferDecoder
283  *************************************************************/
284 
285 /* virtual */
286 status_t
287 BMediaBufferDecoder::GetNextChunk(const void **chunkData,
288 								  size_t *chunkLen,
289                                   media_header *mh)
290 {
291 	if (!fBufferSize)
292 		return B_LAST_BUFFER_ERROR;
293 
294 	*chunkData = fBuffer;
295 	*chunkLen = fBufferSize;
296 	fBufferSize = 0;
297 	return B_OK;
298 }
299