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