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