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