xref: /haiku/src/kits/media/MediaWriter.cpp (revision 13581b3d2a71545960b98fefebc5225b5bf29072)
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 
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 	fStreamInfos(),
52 	fFileFormat(fileFormat)
53 {
54 	CALLED();
55 
56 	gPluginManager.CreateWriter(&fWriter, fFileFormat, fTarget);
57 }
58 
59 
60 MediaWriter::~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 
78 status_t
79 MediaWriter::InitCheck()
80 {
81 	CALLED();
82 
83 	return fWriter != NULL ? fWriter->Init(&fFileFormat) : B_NO_INIT;
84 }
85 
86 
87 BDataIO*
88 MediaWriter::Target() const
89 {
90 	return fTarget;
91 }
92 
93 
94 void
95 MediaWriter::GetFileFormatInfo(media_file_format* _fileFormat) const
96 {
97 	CALLED();
98 
99 	if (_fileFormat != NULL)
100 		*_fileFormat = fFileFormat;
101 }
102 
103 
104 status_t
105 MediaWriter::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 
155 status_t
156 MediaWriter::SetCopyright(const char* copyright)
157 {
158 	if (fWriter == NULL)
159 		return B_NO_INIT;
160 
161 	return fWriter->SetCopyright(copyright);
162 }
163 
164 
165 status_t
166 MediaWriter::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 
179 status_t
180 MediaWriter::CommitHeader()
181 {
182 	if (fWriter == NULL)
183 		return B_NO_INIT;
184 
185 	return fWriter->CommitHeader();
186 }
187 
188 
189 status_t
190 MediaWriter::Flush()
191 {
192 	if (fWriter == NULL)
193 		return B_NO_INIT;
194 
195 	return fWriter->Flush();
196 }
197 
198 
199 status_t
200 MediaWriter::Close()
201 {
202 	if (fWriter == NULL)
203 		return B_NO_INIT;
204 
205 	return fWriter->Close();
206 }
207 
208 
209 status_t
210 MediaWriter::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 
224 status_t
225 MediaWriter::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