xref: /haiku/src/kits/media/MediaEncoder.cpp (revision 1f0635d2277dcd0818dc7f539c1cb1b296f6444b)
1 /*
2  * Copyright 2015, Dario Casalinuovo
3  * Copyright 2010, Oleg Krysenkov, beos344@mail.ru.
4  * Copyright 2012, Fredrik Modéen, [firstname]@[lastname].se.
5  * Copyright 2004-2007, Marcus Overhagen. All rights reserved.
6  * Distributed under the terms of the MIT License.
7  */
8 
9 
10 #include <MediaEncoder.h>
11 
12 #include <CodecRoster.h>
13 #include <Encoder.h>
14 
15 #include <new>
16 
17 #include "MediaDebug.h"
18 
19 using namespace BCodecKit;
20 
21 
22 /*************************************************************
23  * public BMediaEncoder
24  *************************************************************/
25 
26 BMediaEncoder::BMediaEncoder()
27 	:
28 	fEncoder(NULL),
29 	fInitStatus(B_NO_INIT)
30 {
31 	CALLED();
32 }
33 
34 
35 BMediaEncoder::BMediaEncoder(const media_format* outputFormat)
36 	:
37 	fEncoder(NULL),
38 	fInitStatus(B_NO_INIT)
39 {
40 	CALLED();
41 	SetTo(outputFormat);
42 }
43 
44 
45 BMediaEncoder::BMediaEncoder(const media_codec_info* mci)
46 	:
47 	fEncoder(NULL),
48 	fInitStatus(B_NO_INIT)
49 {
50 	CALLED();
51 	SetTo(mci);
52 }
53 
54 
55 /* virtual */
56 BMediaEncoder::~BMediaEncoder()
57 {
58 	CALLED();
59 	ReleaseEncoder();
60 }
61 
62 
63 status_t
64 BMediaEncoder::InitCheck() const
65 {
66 	return fInitStatus;
67 }
68 
69 
70 status_t
71 BMediaEncoder::SetTo(const media_format* outputFormat)
72 {
73 	CALLED();
74 
75 	status_t err = B_ERROR;
76 	ReleaseEncoder();
77 
78 	if (outputFormat == NULL)
79 		return fInitStatus;
80 
81 	media_format format = *outputFormat;
82 	err = BCodecRoster::InstantiateEncoder(&fEncoder, format);
83 	if (fEncoder != NULL && err == B_OK) {
84 		err = _AttachToEncoder();
85 		if (err == B_OK)
86 			return err;
87 	}
88 	ReleaseEncoder();
89 	fInitStatus = err;
90 	return err;
91 }
92 
93 
94 status_t
95 BMediaEncoder::SetTo(const media_codec_info* mci)
96 {
97 	CALLED();
98 
99 	ReleaseEncoder();
100 	status_t err = BCodecRoster::InstantiateEncoder(&fEncoder, mci, 0);
101 	if (fEncoder != NULL && err == B_OK) {
102 		err = _AttachToEncoder();
103 		if (err == B_OK) {
104 			fInitStatus = B_OK;
105 			return B_OK;
106 		}
107 	}
108 
109 	ReleaseEncoder();
110 	fInitStatus = err;
111 	return err;
112 }
113 
114 
115 status_t
116 BMediaEncoder::SetFormat(media_format* inputFormat,
117 	media_format* outputFormat, media_file_format* mfi)
118 {
119 	CALLED();
120 	TRACE("BMediaEncoder::SetFormat. Input = %d, Output = %d\n",
121 		inputFormat->type, outputFormat->type);
122 
123 	if (!fEncoder)
124 		return B_NO_INIT;
125 
126 	if (outputFormat != NULL)
127 		SetTo(outputFormat);
128 
129 	//TODO: How we support mfi?
130 	return fEncoder->SetUp(inputFormat);
131 }
132 
133 
134 status_t
135 BMediaEncoder::Encode(const void* buffer,
136 	int64 frameCount, media_encode_info* info)
137 {
138 	CALLED();
139 
140 	if (!fEncoder)
141 		return B_NO_INIT;
142 
143 	return fEncoder->Encode(buffer, frameCount, info);
144 }
145 
146 
147 status_t
148 BMediaEncoder::GetEncodeParameters(encode_parameters* parameters) const
149 {
150 	CALLED();
151 
152 	if (fEncoder == NULL)
153 		return B_NO_INIT;
154 
155 	return fEncoder->GetEncodeParameters(parameters);
156 }
157 
158 
159 status_t
160 BMediaEncoder::SetEncodeParameters(encode_parameters* parameters)
161 {
162 	CALLED();
163 
164 	if (fEncoder == NULL)
165 		return B_NO_INIT;
166 
167 	return fEncoder->SetEncodeParameters(parameters);
168 }
169 
170 
171 /*************************************************************
172  * protected BMediaEncoder
173  *************************************************************/
174 
175 /* virtual */ status_t
176 BMediaEncoder::AddTrackInfo(uint32 code, const char* data, size_t size)
177 {
178 	CALLED();
179 
180 	if (fEncoder == NULL)
181 		return B_NO_INIT;
182 
183 	return fEncoder->AddTrackInfo(code, data, size);
184 }
185 
186 
187 /*************************************************************
188  * private BMediaEncoder
189  *************************************************************/
190 
191 /*
192 //	unimplemented
193 BMediaEncoder::BMediaEncoder(const BMediaEncoder &);
194 BMediaEncoder::BMediaEncoder & operator=(const BMediaEncoder &);
195 */
196 
197 /* static */ status_t
198 BMediaEncoder::write_chunk(void* classptr, const void* chunk_data,
199 	size_t chunk_len, media_encode_info* info)
200 {
201 	CALLED();
202 
203 	BMediaEncoder* encoder = static_cast<BMediaEncoder*>(classptr);
204 	if (encoder == NULL)
205 		return B_BAD_VALUE;
206 	return encoder->WriteChunk(chunk_data, chunk_len, info);
207 }
208 
209 
210 void
211 BMediaEncoder::Init()
212 {
213 	UNIMPLEMENTED();
214 }
215 
216 
217 void
218 BMediaEncoder::ReleaseEncoder()
219 {
220 	CALLED();
221 	if (fEncoder != NULL) {
222 		BCodecRoster::ReleaseEncoder(fEncoder);
223 		fEncoder = NULL;
224 	}
225 	fInitStatus = B_NO_INIT;
226 }
227 
228 
229 status_t
230 BMediaEncoder::_AttachToEncoder()
231 {
232 	class MediaEncoderChunkWriter : public BChunkWriter {
233 		public:
234 			MediaEncoderChunkWriter(BMediaEncoder* encoder)
235 			{
236 				fEncoder = encoder;
237 			}
238 			virtual status_t WriteChunk(const void* chunkBuffer,
239 				size_t chunkSize, media_encode_info* encodeInfo)
240 			{
241 				return fEncoder->WriteChunk(chunkBuffer, chunkSize, encodeInfo);
242 			}
243 		private:
244 			BMediaEncoder* fEncoder;
245 	} *writer = new(std::nothrow) MediaEncoderChunkWriter(this);
246 
247 	if (!writer)
248 		return B_NO_MEMORY;
249 
250 	fEncoder->SetChunkWriter(writer);
251 	return B_OK;
252 }
253 
254 
255 status_t BMediaEncoder::_Reserved_BMediaEncoder_0(int32 arg, ...) { return B_ERROR; }
256 status_t BMediaEncoder::_Reserved_BMediaEncoder_1(int32 arg, ...) { return B_ERROR; }
257 status_t BMediaEncoder::_Reserved_BMediaEncoder_2(int32 arg, ...) { return B_ERROR; }
258 status_t BMediaEncoder::_Reserved_BMediaEncoder_3(int32 arg, ...) { return B_ERROR; }
259 status_t BMediaEncoder::_Reserved_BMediaEncoder_4(int32 arg, ...) { return B_ERROR; }
260 status_t BMediaEncoder::_Reserved_BMediaEncoder_5(int32 arg, ...) { return B_ERROR; }
261 status_t BMediaEncoder::_Reserved_BMediaEncoder_6(int32 arg, ...) { return B_ERROR; }
262 status_t BMediaEncoder::_Reserved_BMediaEncoder_7(int32 arg, ...) { return B_ERROR; }
263 status_t BMediaEncoder::_Reserved_BMediaEncoder_8(int32 arg, ...) { return B_ERROR; }
264 status_t BMediaEncoder::_Reserved_BMediaEncoder_9(int32 arg, ...) { return B_ERROR; }
265 status_t BMediaEncoder::_Reserved_BMediaEncoder_10(int32 arg, ...) { return B_ERROR; }
266 status_t BMediaEncoder::_Reserved_BMediaEncoder_11(int32 arg, ...) { return B_ERROR; }
267 status_t BMediaEncoder::_Reserved_BMediaEncoder_12(int32 arg, ...) { return B_ERROR; }
268 status_t BMediaEncoder::_Reserved_BMediaEncoder_13(int32 arg, ...) { return B_ERROR; }
269 status_t BMediaEncoder::_Reserved_BMediaEncoder_14(int32 arg, ...) { return B_ERROR; }
270 status_t BMediaEncoder::_Reserved_BMediaEncoder_15(int32 arg, ...) { return B_ERROR; }
271 
272 /*************************************************************
273  * public BMediaBufferEncoder
274  *************************************************************/
275 
276 BMediaBufferEncoder::BMediaBufferEncoder()
277 	:
278 	BMediaEncoder(),
279 	fBuffer(NULL)
280 {
281 	CALLED();
282 }
283 
284 
285 BMediaBufferEncoder::BMediaBufferEncoder(const media_format* outputFormat)
286 	:
287 	BMediaEncoder(outputFormat),
288 	fBuffer(NULL)
289 {
290 	CALLED();
291 }
292 
293 
294 BMediaBufferEncoder::BMediaBufferEncoder(const media_codec_info* mci)
295 	:
296 	BMediaEncoder(mci),
297 	fBuffer(NULL)
298 {
299 	CALLED();
300 }
301 
302 
303 status_t
304 BMediaBufferEncoder::EncodeToBuffer(void* outputBuffer,
305 	size_t* outputSize, const void* inputBuffer,
306 	int64 frameCount, media_encode_info* info)
307 {
308 	CALLED();
309 
310 	status_t error;
311 	fBuffer = outputBuffer;
312 	fBufferSize = *outputSize;
313 	error = Encode(inputBuffer, frameCount, info);
314 	if (fBuffer) {
315 		fBuffer = NULL;
316 		*outputSize = 0;
317 	} else {
318 		*outputSize = fBufferSize;
319 	}
320 	return error;
321 }
322 
323 
324 /*************************************************************
325  * public BMediaBufferEncoder
326  *************************************************************/
327 
328 status_t
329 BMediaBufferEncoder::WriteChunk(const void* chunkData,
330 	size_t chunkLen, media_encode_info* info)
331 {
332 	CALLED();
333 
334 	if (fBuffer == NULL)
335 		return B_ENTRY_NOT_FOUND;
336 
337 	if (chunkLen > (size_t)fBufferSize) {
338 		memcpy(fBuffer, chunkData, fBufferSize);
339 		fBuffer = NULL;
340 		return B_DEVICE_FULL;
341 	}
342 
343 	memcpy(fBuffer, chunkData, chunkLen);
344 	fBufferSize = chunkLen;
345 	fBuffer = NULL;
346 	return B_NO_ERROR;
347 }
348