/* * Copyright 2009, Stephan Aßmus * Copyright 2002-2004, Marcus Overhagen * All rights reserved. Distributed under the terms of the MIT license. */ #include #include #include #include #include #include #include #include "MediaDebug.h" #include "MediaExtractor.h" #include "MediaStreamer.h" #include "MediaWriter.h" BMediaFile::BMediaFile(const entry_ref* ref) { CALLED(); _Init(); fDeleteSource = true; _InitReader(new(std::nothrow) BFile(ref, O_RDONLY)); } BMediaFile::BMediaFile(BDataIO* source) { CALLED(); _Init(); _InitReader(source); } BMediaFile::BMediaFile(const entry_ref* ref, int32 flags) { CALLED(); _Init(); fDeleteSource = true; _InitReader(new(std::nothrow) BFile(ref, O_RDONLY), NULL, flags); } BMediaFile::BMediaFile(BDataIO* source, int32 flags) { CALLED(); _Init(); _InitReader(source, NULL, flags); } BMediaFile::BMediaFile(const entry_ref* ref, const media_file_format* mfi, int32 flags) { CALLED(); _Init(); fDeleteSource = true; _InitWriter(new(std::nothrow) BFile(ref, B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY), NULL, mfi, flags); } BMediaFile::BMediaFile(BDataIO* destination, const media_file_format* mfi, int32 flags) { CALLED(); _Init(); _InitWriter(destination, NULL, mfi, flags); } // File will be set later by SetTo() BMediaFile::BMediaFile(const media_file_format* mfi, int32 flags) { debugger("BMediaFile::BMediaFile not implemented"); } BMediaFile::BMediaFile(const BUrl& url) { CALLED(); _Init(); fDeleteSource = true; _InitReader(NULL, &url); } BMediaFile::BMediaFile(const BUrl& url, int32 flags) { CALLED(); _Init(); fDeleteSource = true; _InitReader(NULL, &url, flags); } BMediaFile::BMediaFile(const BUrl& destination, const media_file_format* mfi, int32 flags) { CALLED(); _Init(); fDeleteSource = true; _InitWriter(NULL, &destination, mfi, flags); // TODO: Implement streaming server support, it's // a pretty complex thing compared to client mode // and will require to expand the current BMediaFile // design to be aware of it. } status_t BMediaFile::SetTo(const entry_ref* ref) { CALLED(); if (ref == NULL) return B_BAD_VALUE; _UnInit(); fDeleteSource = true; _InitReader(new(std::nothrow) BFile(ref, O_RDONLY)); return fErr; } status_t BMediaFile::SetTo(BDataIO* destination) { CALLED(); if (destination == NULL) return B_BAD_VALUE; _UnInit(); _InitReader(destination); return fErr; } status_t BMediaFile::SetTo(const BUrl& url) { CALLED(); _UnInit(); _InitReader(NULL, &url); return fErr; } BMediaFile::~BMediaFile() { CALLED(); _UnInit(); } status_t BMediaFile::InitCheck() const { CALLED(); return fErr; } status_t BMediaFile::GetFileFormatInfo(media_file_format* mfi) const { CALLED(); if (mfi == NULL) return B_BAD_VALUE; if (fErr) return B_ERROR; *mfi = fMFI; return B_OK; } status_t BMediaFile::GetMetaData(BMessage* _data) const { if (fExtractor == NULL) return B_NO_INIT; if (_data == NULL) return B_BAD_VALUE; _data->MakeEmpty(); return fExtractor->GetMetaData(_data); } const char* BMediaFile::Copyright() const { return fExtractor->Copyright(); } int32 BMediaFile::CountTracks() const { return fTrackNum; } // Can be called multiple times with the same index. You must call // ReleaseTrack() when you're done with a track. BMediaTrack* BMediaFile::TrackAt(int32 index) { CALLED(); if (fTrackList == NULL || fExtractor == NULL || index < 0 || index >= fTrackNum) { return NULL; } if (fTrackList[index] == NULL) { TRACE("BMediaFile::TrackAt, creating new track for index %" B_PRId32 "\n", index); fTrackList[index] = new(std::nothrow) BMediaTrack(fExtractor, index); TRACE("BMediaFile::TrackAt, new track is %p\n", fTrackList[index]); } return fTrackList[index]; } // Release the resource used by a given BMediaTrack object, to reduce // the memory usage of your application. The specific 'track' object // can no longer be used, but you can create another one by calling // TrackAt() with the same track index. status_t BMediaFile::ReleaseTrack(BMediaTrack* track) { CALLED(); if (!fTrackList || !track) return B_ERROR; for (int32 i = 0; i < fTrackNum; i++) { if (fTrackList[i] == track) { TRACE("BMediaFile::ReleaseTrack, releasing track %p with index " "%" B_PRId32 "\n", track, i); delete track; fTrackList[i] = NULL; return B_OK; } } fprintf(stderr, "BMediaFile::ReleaseTrack track %p not found\n", track); return B_ERROR; } status_t BMediaFile::ReleaseAllTracks() { CALLED(); if (!fTrackList) return B_ERROR; for (int32 i = 0; i < fTrackNum; i++) { if (fTrackList[i]) { TRACE("BMediaFile::ReleaseAllTracks, releasing track %p with " "index %" B_PRId32 "\n", fTrackList[i], i); delete fTrackList[i]; fTrackList[i] = NULL; } } return B_OK; } // Create and add a track to the media file BMediaTrack* BMediaFile::CreateTrack(media_format* mediaFormat, const media_codec_info* codecInfo, uint32 flags) { if (mediaFormat == NULL) return NULL; // NOTE: It is allowed to pass NULL for codecInfo. In that case, the // track won't have an Encoder and you can only use WriteChunk() with // already encoded data. // Make room for the new track. BMediaTrack** trackList = (BMediaTrack**)realloc(fTrackList, (fTrackNum + 1) * sizeof(BMediaTrack*)); if (trackList == NULL) return NULL; int32 streamIndex = fTrackNum; fTrackList = trackList; fTrackNum += 1; BMediaTrack* track = new(std::nothrow) BMediaTrack(fWriter, streamIndex, mediaFormat, codecInfo); fTrackList[streamIndex] = track; return track; } // Create and add a raw track to the media file (it has no encoder) BMediaTrack* BMediaFile::CreateTrack(media_format* mf, uint32 flags) { return CreateTrack(mf, NULL, flags); } // For BeOS R5 compatibility extern "C" BMediaTrack* CreateTrack__10BMediaFileP12media_formatPC16media_codec_info( BMediaFile* self, media_format* mf, const media_codec_info* mci); BMediaTrack* CreateTrack__10BMediaFileP12media_formatPC16media_codec_info(BMediaFile* self, media_format* mf, const media_codec_info* mci) { return self->CreateTrack(mf, mci, 0); } // For BeOS R5 compatibility extern "C" BMediaTrack* CreateTrack__10BMediaFileP12media_format( BMediaFile* self, media_format* mf); BMediaTrack* CreateTrack__10BMediaFileP12media_format(BMediaFile* self, media_format* mf) { return self->CreateTrack(mf, NULL, 0); } // Lets you set the copyright info for the entire file status_t BMediaFile::AddCopyright(const char* copyright) { if (fWriter == NULL) return B_NO_INIT; return fWriter->SetCopyright(copyright); } // Call this to add user-defined chunks to a file (if they're supported) status_t BMediaFile::AddChunk(int32 type, const void* data, size_t size) { UNIMPLEMENTED(); return B_OK; } // After you have added all the tracks you want, call this status_t BMediaFile::CommitHeader() { if (fWriter == NULL) return B_NO_INIT; return fWriter->CommitHeader(); } // After you have written all the data to the track objects, call this status_t BMediaFile::CloseFile() { if (fWriter == NULL) return B_NO_INIT; return fWriter->Close(); } // This is for controlling file format parameters // returns a copy of the parameter web status_t BMediaFile::GetParameterWeb(BParameterWeb** outWeb) { UNIMPLEMENTED(); return B_ERROR; } // deprecated BeOS R5 API BParameterWeb* BMediaFile::Web() { UNIMPLEMENTED(); return 0; } status_t BMediaFile::GetParameterValue(int32 id, void* value, size_t* size) { UNIMPLEMENTED(); return B_OK; } status_t BMediaFile::SetParameterValue(int32 id, const void* value, size_t size) { UNIMPLEMENTED(); return B_OK; } BView* BMediaFile::GetParameterView() { UNIMPLEMENTED(); return 0; } status_t BMediaFile::Perform(int32 selector, void* data) { UNIMPLEMENTED(); return B_OK; } status_t BMediaFile::ControlFile(int32 selector, void* ioData, size_t size) { UNIMPLEMENTED(); return B_ERROR; } // #pragma mark - private void BMediaFile::_Init() { CALLED(); fSource = NULL; fTrackNum = 0; fTrackList = NULL; fExtractor = NULL; fStreamer = NULL; fWriter = NULL; fWriterID = 0; fErr = B_OK; fDeleteSource = false; // not used so far: fEncoderMgr = NULL; fWriterMgr = NULL; fFileClosed = false; } void BMediaFile::_UnInit() { ReleaseAllTracks(); free(fTrackList); fTrackList = NULL; fTrackNum = 0; // Tells the extractor to stop its asynchronous processing // before deleting its source if (fExtractor != NULL) fExtractor->StopProcessing(); if (fDeleteSource) { delete fSource; fDeleteSource = false; } fSource = NULL; // Deleting the extractor or writer can cause unloading of the plugins. // The source must be deleted before that, because it can come from a // plugin (for example the http_streamer) delete fExtractor; fExtractor = NULL; delete fWriter; fWriter = NULL; delete fStreamer; fStreamer = NULL; } void BMediaFile::_InitReader(BDataIO* source, const BUrl* url, int32 flags) { CALLED(); if (source == NULL && url == NULL) { fErr = B_NO_MEMORY; return; } if (source == NULL) _InitStreamer(*url, &source); else if (BFile* file = dynamic_cast(source)) fErr = file->InitCheck(); if (fErr != B_OK) return; fExtractor = new(std::nothrow) MediaExtractor(source, flags); if (fExtractor == NULL) fErr = B_NO_MEMORY; else fErr = fExtractor->InitCheck(); if (fErr != B_OK) return; fSource = source; fExtractor->GetFileFormatInfo(&fMFI); fTrackNum = fExtractor->StreamCount(); fTrackList = (BMediaTrack**)malloc(fTrackNum * sizeof(BMediaTrack*)); if (fTrackList == NULL) { fErr = B_NO_MEMORY; return; } memset(fTrackList, 0, fTrackNum * sizeof(BMediaTrack*)); } void BMediaFile::_InitWriter(BDataIO* target, const BUrl* url, const media_file_format* fileFormat, int32 flags) { CALLED(); if (fileFormat == NULL) { fErr = B_BAD_VALUE; return; } if (target == NULL && url == NULL) { fErr = B_NO_MEMORY; return; } fMFI = *fileFormat; if (target == NULL) { _InitStreamer(*url, &target); if (fErr != B_OK) return; } fWriter = new(std::nothrow) MediaWriter(target, fMFI); if (fWriter == NULL) fErr = B_NO_MEMORY; else fErr = fWriter->InitCheck(); if (fErr != B_OK) return; // Get the actual source from the writer fSource = fWriter->Target(); fTrackNum = 0; } void BMediaFile::_InitStreamer(const BUrl& url, BDataIO** adapter) { if (fStreamer != NULL) delete fStreamer; TRACE(url.UrlString()); fStreamer = new(std::nothrow) MediaStreamer(url); if (fStreamer == NULL) { fErr = B_NO_MEMORY; return; } fErr = fStreamer->CreateAdapter(adapter); } /* //unimplemented BMediaFile::BMediaFile(); BMediaFile::BMediaFile(const BMediaFile&); BMediaFile::BMediaFile& operator=(const BMediaFile&); */ status_t BMediaFile::_Reserved_BMediaFile_0(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_1(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_2(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_3(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_4(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_5(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_6(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_7(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_8(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_9(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_10(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_11(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_12(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_13(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_14(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_15(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_16(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_17(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_18(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_19(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_20(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_21(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_22(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_23(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_24(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_25(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_26(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_27(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_28(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_29(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_30(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_31(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_32(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_33(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_34(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_35(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_36(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_37(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_38(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_39(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_40(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_41(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_42(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_43(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_44(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_45(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_46(int32 arg, ...) { return B_ERROR; } status_t BMediaFile::_Reserved_BMediaFile_47(int32 arg, ...) { return B_ERROR; }