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