xref: /haiku/src/kits/media/MediaWriter.cpp (revision 44d19f4d32b8f7e9c01f00294c87ca5cc2e057f7)
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 
22 class MediaExtractorChunkWriter : public ChunkWriter {
23 public:
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 
38 private:
39 	MediaWriter*	fWriter;
40 	int32			fStreamIndex;
41 };
42 
43 
44 // #pragma mark -
45 
46 
47 MediaWriter::MediaWriter(BDataIO* target, const media_file_format& fileFormat)
48 	:
49 	fTarget(target),
50 	fWriter(NULL),
51 	fStreamer(NULL),
52 	fStreamInfos(),
53 	fFileFormat(fileFormat)
54 {
55 	CALLED();
56 
57 	gPluginManager.CreateWriter(&fWriter, fFileFormat, fTarget);
58 }
59 
60 
61 MediaWriter::MediaWriter(BUrl* url, const media_file_format& fileFormat)
62 	:
63 	fTarget(NULL),
64 	fWriter(NULL),
65 	fStreamer(NULL),
66 	fStreamInfos(),
67 	fFileFormat(fileFormat)
68 {
69 	CALLED();
70 
71 	if (gPluginManager.CreateStreamer(&fStreamer, url, &fTarget) != B_OK)
72 		return;
73 
74 	gPluginManager.CreateWriter(&fWriter, fFileFormat, fTarget);
75 }
76 
77 
78 MediaWriter::~MediaWriter()
79 {
80 	CALLED();
81 
82 	if (fWriter != NULL) {
83 		// free all stream cookies
84 		// and chunk caches
85 		StreamInfo* info;
86 		for (fStreamInfos.Rewind(); fStreamInfos.GetNext(&info);)
87 			fWriter->FreeCookie(info->cookie);
88 
89 		gPluginManager.DestroyWriter(fWriter);
90 	}
91 
92 	// fTarget is owned by the BMediaFile
93 }
94 
95 
96 status_t
97 MediaWriter::InitCheck()
98 {
99 	CALLED();
100 
101 	return fWriter != NULL ? fWriter->Init(&fFileFormat) : B_NO_INIT;
102 }
103 
104 
105 BDataIO*
106 MediaWriter::Target() const
107 {
108 	return fTarget;
109 }
110 
111 
112 void
113 MediaWriter::GetFileFormatInfo(media_file_format* _fileFormat) const
114 {
115 	CALLED();
116 
117 	if (_fileFormat != NULL)
118 		*_fileFormat = fFileFormat;
119 }
120 
121 
122 status_t
123 MediaWriter::CreateEncoder(Encoder** _encoder,
124 	const media_codec_info* codecInfo, media_format* format, uint32 flags)
125 {
126 	CALLED();
127 
128 	if (fWriter == NULL)
129 		return B_NO_INIT;
130 
131 	// TODO: Here we should work out a way so that if there is a setup
132 	// failure we can try the next encoder.
133 	Encoder* encoder;
134 	status_t ret = gPluginManager.CreateEncoder(&encoder, codecInfo, flags);
135 	if (ret != B_OK) {
136 		ERROR("MediaWriter::CreateEncoder gPluginManager.CreateEncoder "
137 			"failed, codec: %s\n", codecInfo->pretty_name);
138 		return ret;
139 	}
140 
141 	StreamInfo info;
142 	ret = fWriter->AllocateCookie(&info.cookie, format, codecInfo);
143 	if (ret != B_OK) {
144 		gPluginManager.DestroyEncoder(encoder);
145 		return ret;
146 	}
147 
148 	int32 streamIndex = fStreamInfos.CountItems();
149 
150 	if (!fStreamInfos.Insert(info)) {
151 		gPluginManager.DestroyEncoder(encoder);
152 		ERROR("MediaWriter::CreateEncoder can't create StreamInfo "
153 			"for stream %" B_PRId32 "\n", streamIndex);
154 		return B_NO_MEMORY;
155 	}
156 
157 	ChunkWriter* chunkWriter = new(std::nothrow) MediaExtractorChunkWriter(
158 		this, streamIndex);
159 	if (chunkWriter == NULL) {
160 		gPluginManager.DestroyEncoder(encoder);
161 		ERROR("MediaWriter::CreateEncoder can't create ChunkWriter "
162 			"for stream %" B_PRId32 "\n", streamIndex);
163 		return B_NO_MEMORY;
164 	}
165 
166 	encoder->SetChunkWriter(chunkWriter);
167 	*_encoder = encoder;
168 
169 	return B_OK;
170 }
171 
172 
173 status_t
174 MediaWriter::SetCopyright(const char* copyright)
175 {
176 	if (fWriter == NULL)
177 		return B_NO_INIT;
178 
179 	return fWriter->SetCopyright(copyright);
180 }
181 
182 
183 status_t
184 MediaWriter::SetCopyright(int32 streamIndex, const char* copyright)
185 {
186 	if (fWriter == NULL)
187 		return B_NO_INIT;
188 
189 	StreamInfo* info;
190 	if (!fStreamInfos.Get(streamIndex, &info))
191 		return B_BAD_INDEX;
192 
193 	return fWriter->SetCopyright(info->cookie, copyright);
194 }
195 
196 
197 status_t
198 MediaWriter::CommitHeader()
199 {
200 	if (fWriter == NULL)
201 		return B_NO_INIT;
202 
203 	return fWriter->CommitHeader();
204 }
205 
206 
207 status_t
208 MediaWriter::Flush()
209 {
210 	if (fWriter == NULL)
211 		return B_NO_INIT;
212 
213 	return fWriter->Flush();
214 }
215 
216 
217 status_t
218 MediaWriter::Close()
219 {
220 	if (fWriter == NULL)
221 		return B_NO_INIT;
222 
223 	return fWriter->Close();
224 }
225 
226 
227 status_t
228 MediaWriter::AddTrackInfo(int32 streamIndex, uint32 code,
229 	const void* data, size_t size, uint32 flags)
230 {
231 	if (fWriter == NULL)
232 		return B_NO_INIT;
233 
234 	StreamInfo* info;
235 	if (!fStreamInfos.Get(streamIndex, &info))
236 		return B_BAD_INDEX;
237 
238 	return fWriter->AddTrackInfo(info->cookie, code, data, size, flags);
239 }
240 
241 
242 status_t
243 MediaWriter::WriteChunk(int32 streamIndex, const void* chunkBuffer,
244 	size_t chunkSize, media_encode_info* encodeInfo)
245 {
246 	if (fWriter == NULL)
247 		return B_NO_INIT;
248 
249 	StreamInfo* info;
250 	if (!fStreamInfos.Get(streamIndex, &info))
251 		return B_BAD_INDEX;
252 
253 	return fWriter->WriteChunk(info->cookie, chunkBuffer, chunkSize,
254 		encodeInfo);
255 }
256 
257