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