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 "debug.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
87void
88MediaWriter::GetFileFormatInfo(media_file_format* _fileFormat) const
89{
90	CALLED();
91
92	if (_fileFormat != NULL)
93		*_fileFormat = fFileFormat;
94}
95
96
97status_t
98MediaWriter::CreateEncoder(Encoder** _encoder,
99	const media_codec_info* codecInfo, media_format* format, uint32 flags)
100{
101	CALLED();
102
103	if (fWriter == NULL)
104		return B_NO_INIT;
105
106	// TODO: Here we should work out a way so that if there is a setup
107	// failure we can try the next encoder.
108	Encoder* encoder;
109	status_t ret = gPluginManager.CreateEncoder(&encoder, codecInfo, flags);
110	if (ret != B_OK) {
111		ERROR("MediaWriter::CreateEncoder gPluginManager.CreateEncoder "
112			"failed, codec: %s\n", codecInfo->pretty_name);
113		return ret;
114	}
115
116	StreamInfo info;
117	ret = fWriter->AllocateCookie(&info.cookie, format, codecInfo);
118	if (ret != B_OK) {
119		gPluginManager.DestroyEncoder(encoder);
120		return ret;
121	}
122
123	int32 streamIndex = fStreamInfos.CountItems();
124
125	if (!fStreamInfos.Insert(info)) {
126		gPluginManager.DestroyEncoder(encoder);
127		ERROR("MediaWriter::CreateEncoder can't create StreamInfo "
128			"for stream %" B_PRId32 "\n", streamIndex);
129		return B_NO_MEMORY;
130	}
131
132	ChunkWriter* chunkWriter = new(std::nothrow) MediaExtractorChunkWriter(
133		this, streamIndex);
134	if (chunkWriter == NULL) {
135		gPluginManager.DestroyEncoder(encoder);
136		ERROR("MediaWriter::CreateEncoder can't create ChunkWriter "
137			"for stream %" B_PRId32 "\n", streamIndex);
138		return B_NO_MEMORY;
139	}
140
141	encoder->SetChunkWriter(chunkWriter);
142	*_encoder = encoder;
143
144	return B_OK;
145}
146
147
148status_t
149MediaWriter::SetCopyright(const char* copyright)
150{
151	if (fWriter == NULL)
152		return B_NO_INIT;
153
154	return fWriter->SetCopyright(copyright);
155}
156
157
158status_t
159MediaWriter::SetCopyright(int32 streamIndex, const char* copyright)
160{
161	if (fWriter == NULL)
162		return B_NO_INIT;
163
164	StreamInfo* info;
165	if (!fStreamInfos.Get(streamIndex, &info))
166		return B_BAD_INDEX;
167
168	return fWriter->SetCopyright(info->cookie, copyright);
169}
170
171
172status_t
173MediaWriter::CommitHeader()
174{
175	if (fWriter == NULL)
176		return B_NO_INIT;
177
178	return fWriter->CommitHeader();
179}
180
181
182status_t
183MediaWriter::Flush()
184{
185	if (fWriter == NULL)
186		return B_NO_INIT;
187
188	return fWriter->Flush();
189}
190
191
192status_t
193MediaWriter::Close()
194{
195	if (fWriter == NULL)
196		return B_NO_INIT;
197
198	return fWriter->Close();
199}
200
201
202status_t
203MediaWriter::AddTrackInfo(int32 streamIndex, uint32 code,
204	const void* data, size_t size, uint32 flags)
205{
206	if (fWriter == NULL)
207		return B_NO_INIT;
208
209	StreamInfo* info;
210	if (!fStreamInfos.Get(streamIndex, &info))
211		return B_BAD_INDEX;
212
213	return fWriter->AddTrackInfo(info->cookie, code, data, size, flags);
214}
215
216
217status_t
218MediaWriter::WriteChunk(int32 streamIndex, const void* chunkBuffer,
219	size_t chunkSize, media_encode_info* encodeInfo)
220{
221	if (fWriter == NULL)
222		return B_NO_INIT;
223
224	StreamInfo* info;
225	if (!fStreamInfos.Get(streamIndex, &info))
226		return B_BAD_INDEX;
227
228	return fWriter->WriteChunk(info->cookie, chunkBuffer, chunkSize,
229		encodeInfo);
230}
231
232