/* * Copyright 2009-2010, Stephan Aßmus . * All rights reserved. Distributed under the terms of the MIT license. */ #include "MediaWriter.h" #include #include #include #include #include "MediaDebug.h" #include "PluginManager.h" class MediaExtractorChunkWriter : public ChunkWriter { public: MediaExtractorChunkWriter(MediaWriter* writer, int32 streamIndex) : fWriter(writer), fStreamIndex(streamIndex) { } virtual status_t WriteChunk(const void* chunkBuffer, size_t chunkSize, media_encode_info* encodeInfo) { return fWriter->WriteChunk(fStreamIndex, chunkBuffer, chunkSize, encodeInfo); } private: MediaWriter* fWriter; int32 fStreamIndex; }; // #pragma mark - MediaWriter::MediaWriter(BDataIO* target, const media_file_format& fileFormat) : fTarget(target), fWriter(NULL), fStreamInfos(), fFileFormat(fileFormat) { CALLED(); gPluginManager.CreateWriter(&fWriter, fFileFormat, fTarget); } MediaWriter::~MediaWriter() { CALLED(); if (fWriter != NULL) { // free all stream cookies // and chunk caches StreamInfo* info; for (fStreamInfos.Rewind(); fStreamInfos.GetNext(&info);) fWriter->FreeCookie(info->cookie); gPluginManager.DestroyWriter(fWriter); } // fTarget is owned by the BMediaFile } status_t MediaWriter::InitCheck() { CALLED(); return fWriter != NULL ? fWriter->Init(&fFileFormat) : B_NO_INIT; } BDataIO* MediaWriter::Target() const { return fTarget; } void MediaWriter::GetFileFormatInfo(media_file_format* _fileFormat) const { CALLED(); if (_fileFormat != NULL) *_fileFormat = fFileFormat; } status_t MediaWriter::CreateEncoder(Encoder** _encoder, const media_codec_info* codecInfo, media_format* format, uint32 flags) { CALLED(); if (fWriter == NULL) return B_NO_INIT; // TODO: Here we should work out a way so that if there is a setup // failure we can try the next encoder. Encoder* encoder; status_t ret = gPluginManager.CreateEncoder(&encoder, codecInfo, flags); if (ret != B_OK) { ERROR("MediaWriter::CreateEncoder gPluginManager.CreateEncoder " "failed, codec: %s\n", codecInfo->pretty_name); return ret; } StreamInfo info; ret = fWriter->AllocateCookie(&info.cookie, format, codecInfo); if (ret != B_OK) { gPluginManager.DestroyEncoder(encoder); return ret; } int32 streamIndex = fStreamInfos.CountItems(); if (!fStreamInfos.Insert(info)) { gPluginManager.DestroyEncoder(encoder); ERROR("MediaWriter::CreateEncoder can't create StreamInfo " "for stream %" B_PRId32 "\n", streamIndex); return B_NO_MEMORY; } ChunkWriter* chunkWriter = new(std::nothrow) MediaExtractorChunkWriter( this, streamIndex); if (chunkWriter == NULL) { gPluginManager.DestroyEncoder(encoder); ERROR("MediaWriter::CreateEncoder can't create ChunkWriter " "for stream %" B_PRId32 "\n", streamIndex); return B_NO_MEMORY; } encoder->SetChunkWriter(chunkWriter); *_encoder = encoder; return B_OK; } status_t MediaWriter::SetCopyright(const char* copyright) { if (fWriter == NULL) return B_NO_INIT; return fWriter->SetCopyright(copyright); } status_t MediaWriter::SetCopyright(int32 streamIndex, const char* copyright) { if (fWriter == NULL) return B_NO_INIT; StreamInfo* info; if (!fStreamInfos.Get(streamIndex, &info)) return B_BAD_INDEX; return fWriter->SetCopyright(info->cookie, copyright); } status_t MediaWriter::CommitHeader() { if (fWriter == NULL) return B_NO_INIT; return fWriter->CommitHeader(); } status_t MediaWriter::Flush() { if (fWriter == NULL) return B_NO_INIT; return fWriter->Flush(); } status_t MediaWriter::Close() { if (fWriter == NULL) return B_NO_INIT; return fWriter->Close(); } status_t MediaWriter::AddTrackInfo(int32 streamIndex, uint32 code, const void* data, size_t size, uint32 flags) { if (fWriter == NULL) return B_NO_INIT; StreamInfo* info; if (!fStreamInfos.Get(streamIndex, &info)) return B_BAD_INDEX; return fWriter->AddTrackInfo(info->cookie, code, data, size, flags); } status_t MediaWriter::WriteChunk(int32 streamIndex, const void* chunkBuffer, size_t chunkSize, media_encode_info* encodeInfo) { if (fWriter == NULL) return B_NO_INIT; StreamInfo* info; if (!fStreamInfos.Get(streamIndex, &info)) return B_BAD_INDEX; return fWriter->WriteChunk(info->cookie, chunkBuffer, chunkSize, encodeInfo); }