xref: /haiku/src/kits/media/MediaWriter.cpp (revision f8da8f3477d3c18142e59d17d05a545982faa5a8)
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 	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 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, 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 
148 status_t
149 MediaWriter::SetCopyright(const char* copyright)
150 {
151 	if (fWriter == NULL)
152 		return B_NO_INIT;
153 
154 	return fWriter->SetCopyright(copyright);
155 }
156 
157 
158 status_t
159 MediaWriter::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 
172 status_t
173 MediaWriter::CommitHeader()
174 {
175 	if (fWriter == NULL)
176 		return B_NO_INIT;
177 
178 	return fWriter->CommitHeader();
179 }
180 
181 
182 status_t
183 MediaWriter::Flush()
184 {
185 	if (fWriter == NULL)
186 		return B_NO_INIT;
187 
188 	return fWriter->Flush();
189 }
190 
191 
192 status_t
193 MediaWriter::Close()
194 {
195 	if (fWriter == NULL)
196 		return B_NO_INIT;
197 
198 	return fWriter->Close();
199 }
200 
201 
202 status_t
203 MediaWriter::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 
217 status_t
218 MediaWriter::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