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