1/*
2 * Copyright 2009-2010, Stephan A��mus <superstippi@gmx.de>.
3 * All rights reserved. Distributed under the terms of the MIT license.
4 */
5
6
7#include "MediaWriter.h"
8
9#include <new>
10
11#include <stdio.h>
12#include <string.h>
13
14#include <Autolock.h>
15
16#include "MediaDebug.h"
17
18#include "PluginManager.h"
19
20
21
22class MediaExtractorChunkWriter : public ChunkWriter {
23public:
24	MediaExtractorChunkWriter(MediaWriter* writer, int32 streamIndex)
25		:
26		fWriter(writer),
27		fStreamIndex(streamIndex)
28	{
29	}
30
31	virtual status_t WriteChunk(const void* chunkBuffer, size_t chunkSize,
32		media_encode_info* encodeInfo)
33	{
34		return fWriter->WriteChunk(fStreamIndex, chunkBuffer, chunkSize,
35			encodeInfo);
36	}
37
38private:
39	MediaWriter*	fWriter;
40	int32			fStreamIndex;
41};
42
43
44// #pragma mark -
45
46
47MediaWriter::MediaWriter(BDataIO* target, const media_file_format& fileFormat)
48	:
49	fTarget(target),
50	fWriter(NULL),
51	fStreamInfos(),
52	fFileFormat(fileFormat)
53{
54	CALLED();
55
56	gPluginManager.CreateWriter(&fWriter, fFileFormat, fTarget);
57}
58
59
60MediaWriter::~MediaWriter()
61{
62	CALLED();
63
64	if (fWriter != NULL) {
65		// free all stream cookies
66		// and chunk caches
67		StreamInfo* info;
68		for (fStreamInfos.Rewind(); fStreamInfos.GetNext(&info);)
69			fWriter->FreeCookie(info->cookie);
70
71		gPluginManager.DestroyWriter(fWriter);
72	}
73
74	// fTarget is owned by the BMediaFile
75}
76
77
78status_t
79MediaWriter::InitCheck()
80{
81	CALLED();
82
83	return fWriter != NULL ? fWriter->Init(&fFileFormat) : B_NO_INIT;
84}
85
86
87BDataIO*
88MediaWriter::Target() const
89{
90	return fTarget;
91}
92
93
94void
95MediaWriter::GetFileFormatInfo(media_file_format* _fileFormat) const
96{
97	CALLED();
98
99	if (_fileFormat != NULL)
100		*_fileFormat = fFileFormat;
101}
102
103
104status_t
105MediaWriter::CreateEncoder(Encoder** _encoder,
106	const media_codec_info* codecInfo, media_format* format, uint32 flags)
107{
108	CALLED();
109
110	if (fWriter == NULL)
111		return B_NO_INIT;
112
113	// TODO: Here we should work out a way so that if there is a setup
114	// failure we can try the next encoder.
115	Encoder* encoder;
116	status_t ret = gPluginManager.CreateEncoder(&encoder, codecInfo, flags);
117	if (ret != B_OK) {
118		ERROR("MediaWriter::CreateEncoder gPluginManager.CreateEncoder "
119			"failed, codec: %s\n", codecInfo->pretty_name);
120		return ret;
121	}
122
123	StreamInfo info;
124	ret = fWriter->AllocateCookie(&info.cookie, format, codecInfo);
125	if (ret != B_OK) {
126		gPluginManager.DestroyEncoder(encoder);
127		return ret;
128	}
129
130	int32 streamIndex = fStreamInfos.CountItems();
131
132	if (!fStreamInfos.Insert(info)) {
133		gPluginManager.DestroyEncoder(encoder);
134		ERROR("MediaWriter::CreateEncoder can't create StreamInfo "
135			"for stream %" B_PRId32 "\n", streamIndex);
136		return B_NO_MEMORY;
137	}
138
139	ChunkWriter* chunkWriter = new(std::nothrow) MediaExtractorChunkWriter(
140		this, streamIndex);
141	if (chunkWriter == NULL) {
142		gPluginManager.DestroyEncoder(encoder);
143		ERROR("MediaWriter::CreateEncoder can't create ChunkWriter "
144			"for stream %" B_PRId32 "\n", streamIndex);
145		return B_NO_MEMORY;
146	}
147
148	encoder->SetChunkWriter(chunkWriter);
149	*_encoder = encoder;
150
151	return B_OK;
152}
153
154
155status_t
156MediaWriter::SetCopyright(const char* copyright)
157{
158	if (fWriter == NULL)
159		return B_NO_INIT;
160
161	return fWriter->SetCopyright(copyright);
162}
163
164
165status_t
166MediaWriter::SetCopyright(int32 streamIndex, const char* copyright)
167{
168	if (fWriter == NULL)
169		return B_NO_INIT;
170
171	StreamInfo* info;
172	if (!fStreamInfos.Get(streamIndex, &info))
173		return B_BAD_INDEX;
174
175	return fWriter->SetCopyright(info->cookie, copyright);
176}
177
178
179status_t
180MediaWriter::CommitHeader()
181{
182	if (fWriter == NULL)
183		return B_NO_INIT;
184
185	return fWriter->CommitHeader();
186}
187
188
189status_t
190MediaWriter::Flush()
191{
192	if (fWriter == NULL)
193		return B_NO_INIT;
194
195	return fWriter->Flush();
196}
197
198
199status_t
200MediaWriter::Close()
201{
202	if (fWriter == NULL)
203		return B_NO_INIT;
204
205	return fWriter->Close();
206}
207
208
209status_t
210MediaWriter::AddTrackInfo(int32 streamIndex, uint32 code,
211	const void* data, size_t size, uint32 flags)
212{
213	if (fWriter == NULL)
214		return B_NO_INIT;
215
216	StreamInfo* info;
217	if (!fStreamInfos.Get(streamIndex, &info))
218		return B_BAD_INDEX;
219
220	return fWriter->AddTrackInfo(info->cookie, code, data, size, flags);
221}
222
223
224status_t
225MediaWriter::WriteChunk(int32 streamIndex, const void* chunkBuffer,
226	size_t chunkSize, media_encode_info* encodeInfo)
227{
228	if (fWriter == NULL)
229		return B_NO_INIT;
230
231	StreamInfo* info;
232	if (!fStreamInfos.Get(streamIndex, &info))
233		return B_BAD_INDEX;
234
235	return fWriter->WriteChunk(info->cookie, chunkBuffer, chunkSize,
236		encodeInfo);
237}
238
239