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 22class MediaExtractorChunkWriter : public ChunkWriter { 23public: 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 38private: 39 MediaWriter* fWriter; 40 int32 fStreamIndex; 41}; 42 43 44// #pragma mark - 45 46 47MediaWriter::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 60MediaWriter::~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 78status_t 79MediaWriter::InitCheck() 80{ 81 CALLED(); 82 83 return fWriter != NULL ? fWriter->Init(&fFileFormat) : B_NO_INIT; 84} 85 86 87BDataIO* 88MediaWriter::Target() const 89{ 90 return fTarget; 91} 92 93 94void 95MediaWriter::GetFileFormatInfo(media_file_format* _fileFormat) const 96{ 97 CALLED(); 98 99 if (_fileFormat != NULL) 100 *_fileFormat = fFileFormat; 101} 102 103 104status_t 105MediaWriter::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 155status_t 156MediaWriter::SetCopyright(const char* copyright) 157{ 158 if (fWriter == NULL) 159 return B_NO_INIT; 160 161 return fWriter->SetCopyright(copyright); 162} 163 164 165status_t 166MediaWriter::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 179status_t 180MediaWriter::CommitHeader() 181{ 182 if (fWriter == NULL) 183 return B_NO_INIT; 184 185 return fWriter->CommitHeader(); 186} 187 188 189status_t 190MediaWriter::Flush() 191{ 192 if (fWriter == NULL) 193 return B_NO_INIT; 194 195 return fWriter->Flush(); 196} 197 198 199status_t 200MediaWriter::Close() 201{ 202 if (fWriter == NULL) 203 return B_NO_INIT; 204 205 return fWriter->Close(); 206} 207 208 209status_t 210MediaWriter::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 224status_t 225MediaWriter::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