diff --git a/headers/os/media/MediaFile.h b/headers/os/media/MediaFile.h index 902a92cd50..d98830b6bd 100644 --- a/headers/os/media/MediaFile.h +++ b/headers/os/media/MediaFile.h @@ -1,10 +1,11 @@ /* * Copyright 2002-2009, Haiku, Inc. All rights reserved. - * Distributed under the terms of the MIT License. + * Distributed under the terms of the MIT license. */ #ifndef _MEDIA_FILE_H #define _MEDIA_FILE_H + #include #include #include @@ -15,13 +16,13 @@ namespace BPrivate { namespace media { class MediaExtractor; + class MediaWriter; } - class MediaWriter; class _AddonManager; } -// forward declarations +// forward declarations class BMediaTrack; class BParameterWeb; class BView; @@ -50,7 +51,7 @@ enum { class BMediaFile { public: // these four constructors are used for read-only access - BMediaFile(const entry_ref* ref); + BMediaFile(const entry_ref* ref); BMediaFile(BDataIO* source); // BFile is a BDataIO BMediaFile(const entry_ref* ref, int32 flags); @@ -71,14 +72,14 @@ public: status_t SetTo(const entry_ref* ref); status_t SetTo(BDataIO* destination); - + status_t InitCheck() const; // Get info about the underlying file format. status_t GetFileFormatInfo(media_file_format* mfi) const; // - // These functions are for read-only access to a media file. + // These functions are for read-only access to a media file. // The data is read using the BMediaTrack object. // const char* Copyright() const; @@ -136,7 +137,7 @@ private: // deprecated, but for R5 compatibility BParameterWeb* Web(); - // Does nothing, returns B_ERROR, for Zeta compatiblity only + // Does nothing, returns B_ERROR, for Zeta compatiblity only status_t ControlFile(int32 selector, void* ioData, size_t size); @@ -147,7 +148,7 @@ private: BPrivate::_AddonManager* fEncoderMgr; BPrivate::_AddonManager* fWriterMgr; - BPrivate::MediaWriter* fWriter; + BPrivate::media::MediaWriter* fWriter; int32 fWriterID; media_file_format fMFI; @@ -159,8 +160,9 @@ private: void _Init(); void _UnInit(); void _InitReader(BDataIO* source, int32 flags = 0); - void _InitWriter(BDataIO* source, - const media_file_format* mfi, int32 flags); + void _InitWriter(BDataIO* target, + const media_file_format* fileFormat, + int32 flags); BMediaFile(); BMediaFile(const BMediaFile&); diff --git a/headers/os/media/MediaTrack.h b/headers/os/media/MediaTrack.h index c9621da13e..dae299020e 100644 --- a/headers/os/media/MediaTrack.h +++ b/headers/os/media/MediaTrack.h @@ -217,9 +217,9 @@ private: // For write-only access to a BMediaTrack BMediaTrack(BPrivate::media::MediaWriter* writer, - int32 streamIndex, media_format* format, - BPrivate::media::Encoder* encoder, - media_codec_info* codecInfo); + int32 streamIndex, + const media_format* format, + const media_codec_info* codecInfo); void SetupWorkaround(); bool SetupFormatTranslation(const media_format& from, @@ -241,7 +241,7 @@ private: int32 fEncoderID; BPrivate::media::MediaWriter* fWriter; media_format fWriterFormat; - + uint32 fWorkaroundFlags; protected: diff --git a/headers/private/media/EncoderPlugin.h b/headers/private/media/EncoderPlugin.h index 8aaa2b9003..7cba9a43a7 100644 --- a/headers/private/media/EncoderPlugin.h +++ b/headers/private/media/EncoderPlugin.h @@ -21,7 +21,8 @@ class ChunkWriter { public: virtual ~ChunkWriter() {}; virtual status_t WriteChunk(const void* chunkBuffer, - size_t chunkSize, uint32 flags) = 0; + size_t chunkSize, + media_encode_info* encodeInfo) = 0; }; @@ -30,29 +31,42 @@ public: Encoder(); virtual ~Encoder(); - // TODO: I think we may actually need a method to specialize a - // media_format. For example, some codecs may only support certain - // input color spaces, or output color spaces, or multiple of 16 - // width/height... This support is technically even needed for - // MediaFormats.h functionality, although there probably isn't - // an application out there which uses it like that. + // Some codecs may only support certain input color spaces, or output + // color spaces, or multiple of 16 width/height... This method is needed + // for get_next_encoder() functionality. If _acceptedInputFormat is NULL, + // you simply return a status indicating if proposed format is acceptable. + // If it contains wildcards for fields that you have restrictions on, + // return an error. In that case, the user should be using the form of + // get_next_encoder() that allows to specify the accepted format. If + // _acceptedInputFormat is not NULL, copy the proposedFormat into + // _acceptedInputFormat and specialize any wildcards. You must (!) also + // change non-wildcard fields, like the video width if you want to round to + // the nearest multiple of 16 for example. Only if the format is completely + // unacceptable, return an error. + virtual status_t AcceptedFormat( + const media_format* proposedInputFormat, + media_format* _acceptedInputFormat = NULL) + = 0; - virtual status_t SetFormat(const media_file_format& fileFormat, - media_format* _inOutEncodedFormat) = 0; + // The passed media_format may not contain wildcards and must be the same + // format that was passed to get_next_encoder() (or it must be the format + // returned in _acceptedInputFormat). + virtual status_t SetUp(const media_format* inputFormat) = 0; virtual status_t AddTrackInfo(uint32 code, const void* data, - size_t size, uint32 flags = 0) = 0; + size_t size, uint32 flags = 0); virtual status_t GetEncodeParameters( - encode_parameters* parameters) const = 0; + encode_parameters* parameters) const; virtual status_t SetEncodeParameters( - encode_parameters* parameters) const = 0; - + encode_parameters* parameters) const; + virtual status_t Encode(const void* buffer, int64 frameCount, media_encode_info* info) = 0; - + status_t WriteChunk(const void* chunkBuffer, - size_t chunkSize, uint32 flags = 0); + size_t chunkSize, + media_encode_info* encodeInfo); void SetChunkWriter(ChunkWriter* writer); diff --git a/headers/private/media/MediaWriter.h b/headers/private/media/MediaWriter.h index 46be33c89c..31be2c319d 100644 --- a/headers/private/media/MediaWriter.h +++ b/headers/private/media/MediaWriter.h @@ -25,22 +25,24 @@ public: void GetFileFormatInfo(media_file_format* mfi) const; + status_t CreateEncoder(Encoder** _encoder, + const media_codec_info* codecInfo, + uint32 flags = 0); + + status_t SetCopyright(int32 streamIndex, + const char* copyright); status_t SetCopyright(const char* copyright); status_t CommitHeader(); status_t Flush(); status_t Close(); - status_t AddTrackInfo(void* cookie, uint32 code, + status_t AddTrackInfo(int32 streamIndex, uint32 code, const void* data, size_t size, uint32 flags = 0); - status_t CreateEncoder(Encoder** _encoder, - const media_codec_info* codecInfo, - uint32 flags = 0); - - status_t WriteChunk(int32 stream, + status_t WriteChunk(int32 streamIndex, const void* chunkBuffer, size_t chunkSize, - uint32 flags); + media_encode_info* encodeInfo); private: struct StreamInfo { diff --git a/headers/private/media/WriterPlugin.h b/headers/private/media/WriterPlugin.h index 0833658243..07ad8ac283 100644 --- a/headers/private/media/WriterPlugin.h +++ b/headers/private/media/WriterPlugin.h @@ -20,14 +20,17 @@ public: virtual status_t AllocateCookie(void** cookie) = 0; virtual status_t FreeCookie(void* cookie) = 0; - + + virtual status_t SetCopyright(void* cookie, + const char* copyright) = 0; + virtual status_t AddTrackInfo(void* cookie, uint32 code, const void* data, size_t size, uint32 flags = 0) = 0; virtual status_t WriteChunk(void* cookie, const void* chunkBuffer, size_t chunkSize, - uint32 flags) = 0; + media_encode_info* encodeInfo) = 0; BDataIO* Target() const; diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.cpp b/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.cpp index c032899a28..8c4a5b091e 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.cpp +++ b/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.cpp @@ -33,21 +33,31 @@ AVCodecEncoder::~AVCodecEncoder() status_t -AVCodecEncoder::SetFormat(const media_file_format& fileFormat, - media_format* _inOutEncodedFormat) +AVCodecEncoder::AcceptedFormat(const media_format* proposedInputFormat, + media_format* _acceptedInputFormat) { - TRACE("AVCodecEncoder::SetFormat()\n"); + TRACE("AVCodecEncoder::AcceptedFormat(%p, %p)\n", proposedInputFormat, + _acceptedInputFormat); - return B_NOT_SUPPORTED; + if (proposedInputFormat == NULL) + return B_BAD_VALUE; + + if (_acceptedInputFormat != NULL) { + memcpy(_acceptedInputFormat, proposedInputFormat, + sizeof(media_format)); + } + + return B_OK; } status_t -AVCodecEncoder::AddTrackInfo(uint32 code, const void* data, size_t size, - uint32 flags) +AVCodecEncoder::SetUp(const media_format* inputFormat) { - TRACE("AVCodecEncoder::AddTrackInfo(%lu, %p, %ld, %lu)\n", code, data, - size, flags); + TRACE("AVCodecEncoder::SetUp()\n"); + + if (inputFormat == NULL) + return B_BAD_VALUE; return B_NOT_SUPPORTED; } @@ -70,7 +80,7 @@ AVCodecEncoder::SetEncodeParameters(encode_parameters* parameters) const return B_NOT_SUPPORTED; } - + status_t AVCodecEncoder::Encode(const void* buffer, int64 frameCount, media_encode_info* info) diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.h b/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.h index f5a710df6a..9a0e99208c 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.h +++ b/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.h @@ -14,23 +14,23 @@ class AVCodecEncoder : public Encoder { public: AVCodecEncoder(const char* shortName); - - virtual ~AVCodecEncoder(); - - virtual status_t SetFormat(const media_file_format& fileFormat, - media_format* _inOutEncodedFormat); - virtual status_t AddTrackInfo(uint32 code, const void* data, - size_t size, uint32 flags = 0); + virtual ~AVCodecEncoder(); + + virtual status_t AcceptedFormat( + const media_format* proposedInputFormat, + media_format* _acceptedInputFormat = NULL); + + virtual status_t SetUp(const media_format* inputFormat); virtual status_t GetEncodeParameters( encode_parameters* parameters) const; virtual status_t SetEncodeParameters( encode_parameters* parameters) const; - + virtual status_t Encode(const void* buffer, int64 frameCount, media_encode_info* info); - + private: }; diff --git a/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp b/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp index 9969abbdb0..7e8b53ecdb 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp +++ b/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp @@ -172,6 +172,15 @@ AVFormatWriter::FreeCookie(void* _cookie) // #pragma mark - +status_t +AVFormatWriter::SetCopyright(void* cookie, const char* copyright) +{ + TRACE("AVFormatWriter::SetCopyright(%p, %s)\n", cookie, copyright); + + return B_NOT_SUPPORTED; +} + + status_t AVFormatWriter::AddTrackInfo(void* cookie, uint32 code, const void* data, size_t size, uint32 flags) @@ -185,10 +194,10 @@ AVFormatWriter::AddTrackInfo(void* cookie, uint32 code, status_t AVFormatWriter::WriteChunk(void* cookie, const void* chunkBuffer, - size_t chunkSize, uint32 flags) + size_t chunkSize, media_encode_info* encodeInfo) { - TRACE("AVFormatWriter::WriteChunk(%p, %ld, %lu)\n", chunkBuffer, chunkSize, - flags); + TRACE("AVFormatWriter::WriteChunk(%p, %ld, %p)\n", chunkBuffer, chunkSize, + encodeInfo); return B_NOT_SUPPORTED; } diff --git a/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.h b/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.h index 389b18ccb3..923e8c14df 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.h +++ b/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.h @@ -15,7 +15,7 @@ class AVFormatWriter : public Writer { public: AVFormatWriter(); ~AVFormatWriter(); - + virtual status_t SetCopyright(const char* copyright); virtual status_t CommitHeader(); virtual status_t Flush(); @@ -23,14 +23,17 @@ public: virtual status_t AllocateCookie(void** cookie); virtual status_t FreeCookie(void* cookie); - + + virtual status_t SetCopyright(void* cookie, + const char* copyright); + virtual status_t AddTrackInfo(void* cookie, uint32 code, const void* data, size_t size, uint32 flags = 0); virtual status_t WriteChunk(void* cookie, const void* chunkBuffer, size_t chunkSize, - uint32 flags); + media_encode_info* encodeInfo); private: class StreamCookie; diff --git a/src/kits/media/EncoderPlugin.cpp b/src/kits/media/EncoderPlugin.cpp index 7c3f626610..dd0b3462cc 100644 --- a/src/kits/media/EncoderPlugin.cpp +++ b/src/kits/media/EncoderPlugin.cpp @@ -1,4 +1,4 @@ -/* +/* * Copyright 2009, Stephan Aßmus . All rights reserved. * Copyright 2004, Marcus Overhagen. All rights reserved. * Distributed under the terms of the MIT License. @@ -25,11 +25,33 @@ Encoder::~Encoder() delete fChunkWriter; } - + status_t -Encoder::WriteChunk(const void* chunkBuffer, size_t chunkSize, uint32 flags) +Encoder::AddTrackInfo(uint32 code, const void* data, size_t size, uint32 flags) { - return fChunkWriter->WriteChunk(chunkBuffer, chunkSize, flags); + return B_NOT_SUPPORTED; +} + + +status_t +Encoder::GetEncodeParameters(encode_parameters* parameters) const +{ + return B_NOT_SUPPORTED; +} + + +status_t +Encoder::SetEncodeParameters(encode_parameters* parameters) const +{ + return B_NOT_SUPPORTED; +} + + +status_t +Encoder::WriteChunk(const void* chunkBuffer, size_t chunkSize, + media_encode_info* encodeInfo) +{ + return fChunkWriter->WriteChunk(chunkBuffer, chunkSize, encodeInfo); } diff --git a/src/kits/media/MediaFile.cpp b/src/kits/media/MediaFile.cpp index cc8005cf40..40fe43b899 100644 --- a/src/kits/media/MediaFile.cpp +++ b/src/kits/media/MediaFile.cpp @@ -1,18 +1,23 @@ /* - * Copyright (c) 2002-2004, Marcus Overhagen - * All rights reserved. Distributed under the terms of the MIT License. + * 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 "debug.h" #include "MediaExtractor.h" -#include "debug.h" +#include "MediaWriter.h" BMediaFile::BMediaFile(const entry_ref* ref) @@ -20,7 +25,7 @@ BMediaFile::BMediaFile(const entry_ref* ref) CALLED(); _Init(); fDeleteSource = true; - _InitReader(new (std::nothrow) BFile(ref, O_RDONLY)); + _InitReader(new(std::nothrow) BFile(ref, O_RDONLY)); } @@ -37,7 +42,7 @@ BMediaFile::BMediaFile(const entry_ref* ref, int32 flags) CALLED(); _Init(); fDeleteSource = true; - _InitReader(new (std::nothrow) BFile(ref, O_RDONLY), flags); + _InitReader(new(std::nothrow) BFile(ref, O_RDONLY), flags); } @@ -55,7 +60,7 @@ BMediaFile::BMediaFile(const entry_ref* ref, const media_file_format* mfi, CALLED(); _Init(); fDeleteSource = true; - _InitWriter(new (std::nothrow) BFile(ref, O_WRONLY), mfi, flags); + _InitWriter(new(std::nothrow) BFile(ref, O_WRONLY), mfi, flags); } @@ -85,7 +90,7 @@ BMediaFile::SetTo(const entry_ref* ref) _UnInit(); fDeleteSource = true; - _InitReader(new (std::nothrow) BFile(ref, O_RDONLY)); + _InitReader(new(std::nothrow) BFile(ref, O_RDONLY)); return fErr; } @@ -162,7 +167,7 @@ BMediaFile::TrackAt(int32 index) } if (fTrackList[index] == NULL) { TRACE("BMediaFile::TrackAt, creating new track for index %ld\n", index); - fTrackList[index] = new (std::nothrow) BMediaTrack(fExtractor, index); + fTrackList[index] = new(std::nothrow) BMediaTrack(fExtractor, index); TRACE("BMediaFile::TrackAt, new track is %p\n", fTrackList[index]); } return fTrackList[index]; @@ -213,11 +218,32 @@ BMediaFile::ReleaseAllTracks() // Create and add a track to the media file BMediaTrack* -BMediaFile::CreateTrack(media_format* mf, const media_codec_info* mci, - uint32 flags) +BMediaFile::CreateTrack(media_format* mediaFormat, + const media_codec_info* codecInfo, uint32 flags) { - UNIMPLEMENTED(); - return 0; + 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; } @@ -253,10 +279,12 @@ CreateTrack__10BMediaFileP12media_format(BMediaFile* self, media_format* mf) // Lets you set the copyright info for the entire file status_t -BMediaFile::AddCopyright(const char* data) +BMediaFile::AddCopyright(const char* copyright) { - UNIMPLEMENTED(); - return B_OK; + if (fWriter == NULL) + return B_NO_INIT; + + return fWriter->SetCopyright(copyright); } @@ -273,8 +301,10 @@ BMediaFile::AddChunk(int32 type, const void* data, size_t size) status_t BMediaFile::CommitHeader() { - UNIMPLEMENTED(); - return B_OK; + if (fWriter == NULL) + return B_NO_INIT; + + return fWriter->CommitHeader(); } @@ -282,8 +312,10 @@ BMediaFile::CommitHeader() status_t BMediaFile::CloseFile() { - UNIMPLEMENTED(); - return B_OK; + if (fWriter == NULL) + return B_NO_INIT; + + return fWriter->Close(); } // This is for controlling file format parameters @@ -374,7 +406,7 @@ void BMediaFile::_UnInit() { ReleaseAllTracks(); - delete[] fTrackList; + free(fTrackList); fTrackList = NULL; fTrackNum = 0; delete fExtractor; @@ -399,7 +431,7 @@ BMediaFile::_InitReader(BDataIO* source, int32 flags) fSource = source; - fExtractor = new (std::nothrow) MediaExtractor(source, flags); + fExtractor = new(std::nothrow) MediaExtractor(source, flags); if (fExtractor == NULL) fErr = B_NO_MEMORY; else @@ -409,7 +441,7 @@ BMediaFile::_InitReader(BDataIO* source, int32 flags) fExtractor->GetFileFormatInfo(&fMFI); fTrackNum = fExtractor->StreamCount(); - fTrackList = new (std::nothrow) BMediaTrack*[fTrackNum]; + fTrackList = (BMediaTrack**)malloc(fTrackNum * sizeof(BMediaTrack*)); if (fTrackList == NULL) { fErr = B_NO_MEMORY; return; @@ -419,12 +451,33 @@ BMediaFile::_InitReader(BDataIO* source, int32 flags) void -BMediaFile::_InitWriter(BDataIO* source, const media_file_format* mfi, +BMediaFile::_InitWriter(BDataIO* target, const media_file_format* fileFormat, int32 flags) { - UNIMPLEMENTED(); - fSource = source; - fErr = B_NOT_ALLOWED; + CALLED(); + + if (fileFormat == NULL) { + fErr = B_BAD_VALUE; + return; + } + + if (target == NULL) { + fErr = B_NO_MEMORY; + return; + } + + fMFI = *fileFormat; + fSource = target; + + fWriter = new(std::nothrow) MediaWriter(fSource, fMFI); + if (fWriter == NULL) + fErr = B_NO_MEMORY; + else + fErr = fWriter->InitCheck(); + if (fErr != B_OK) + return; + + fTrackNum = 0; } diff --git a/src/kits/media/MediaTrack.cpp b/src/kits/media/MediaTrack.cpp index adcdc0ce61..6171ab7c15 100644 --- a/src/kits/media/MediaTrack.cpp +++ b/src/kits/media/MediaTrack.cpp @@ -1,37 +1,26 @@ /* - * Copyright (c) 2002-2007, Marcus Overhagen - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * Copyright 2009, Stephan Aßmus + * Copyright 2002-2007, Marcus Overhagen + * All rights reserved. Distributed under the terms of the MIT license. */ + #include -#include + +#include + #include #include -#include -#include "MediaExtractor.h" -#include "PluginManager.h" + +#include + #include "debug.h" +#include "MediaExtractor.h" +#include "MediaWriter.h" +#include "PluginManager.h" + + //#define TRACE_MEDIA_TRACK #ifdef TRACE_MEDIA_TRACK #ifndef TRACE @@ -67,7 +56,7 @@ class RawDecoderChunkProvider : public ChunkProvider public: RawDecoderChunkProvider(Decoder *decoder, int buffer_size, int frame_size); virtual ~RawDecoderChunkProvider(); - + status_t GetNextChunk(const void **chunkBuffer, size_t *chunkSize, media_header *mediaHeader); private: @@ -138,7 +127,7 @@ BMediaTrack::EncodedFormat(media_format *out_format) const // for BeOS R5 compatibilitly extern "C" status_t DecodedFormat__11BMediaTrackP12media_format(BMediaTrack *self, media_format *inout_format); -status_t DecodedFormat__11BMediaTrackP12media_format(BMediaTrack *self, +status_t DecodedFormat__11BMediaTrackP12media_format(BMediaTrack *self, media_format *inout_format) { return self->DecodedFormat(inout_format, 0); @@ -153,16 +142,16 @@ BMediaTrack::DecodedFormat(media_format *inout_format, uint32 flags) return B_BAD_VALUE; if (!fExtractor || !fDecoder) return B_NO_INIT; - + _plugin_manager.DestroyDecoder(fRawDecoder); fRawDecoder = 0; #ifdef TRACE_MEDIA_TRACK char s[200]; string_for_format(*inout_format, s, sizeof(s)); - printf("BMediaTrack::DecodedFormat: req1: %s\n", s); + printf("BMediaTrack::DecodedFormat: req1: %s\n", s); #endif - + if ((fWorkaroundFlags & FORCE_RAW_AUDIO) || ((fWorkaroundFlags & IGNORE_ENCODED_AUDIO) && inout_format->type == B_MEDIA_ENCODED_AUDIO)) { inout_format->type = B_MEDIA_RAW_AUDIO; inout_format->u.raw_audio = media_multi_audio_format::wildcard; @@ -195,9 +184,9 @@ BMediaTrack::DecodedFormat(media_format *inout_format, uint32 flags) #ifdef TRACE_MEDIA_TRACK string_for_format(*inout_format, s, sizeof(s)); - printf("BMediaTrack::DecodedFormat: nego: %s\n", s); + printf("BMediaTrack::DecodedFormat: nego: %s\n", s); #endif - + if (inout_format->type == 0) debugger("Decoder didn't set output format type"); if (inout_format->type == B_MEDIA_RAW_AUDIO) { @@ -231,8 +220,8 @@ BMediaTrack::DecodedFormat(media_format *inout_format, uint32 flags) } // string_for_format(*inout_format, s, sizeof(s)); -// printf("BMediaTrack::DecodedFormat: res: %s\n", s); - +// printf("BMediaTrack::DecodedFormat: res: %s\n", s); + return res; } @@ -305,15 +294,15 @@ BMediaTrack::ReadFrames(void *out_buffer, return B_NO_INIT; if (!out_buffer || !out_frameCount) return B_BAD_VALUE; - - status_t result; + + status_t result; media_header header; memset(&header, 0, sizeof(header)); // always clear it first, as the decoder doesn't set all fields if (fRawDecoder) result = fRawDecoder->Decode(out_buffer, out_frameCount, &header, info); - else + else result = fDecoder->Decode(out_buffer, out_frameCount, &header, info); if (result == B_OK) { fCurFrame += *out_frameCount; @@ -324,7 +313,7 @@ BMediaTrack::ReadFrames(void *out_buffer, } if (mh) *mh = header; - + // PRINT(1, "BMediaTrack::ReadFrames: stream %ld, start-time %5Ld.%06Ld, %Ld frames\n", fStream, header.start_time / 1000000, header.start_time % 1000000, *out_frameCount); return result; @@ -354,7 +343,7 @@ BMediaTrack::SeekToTime(bigtime_t *inout_time, int32 flags) uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK) | B_MEDIA_SEEK_TO_TIME; bigtime_t seekTime = *inout_time; - + int64 frame = 0; bigtime_t time = seekTime; status_t result = fExtractor->Seek(fStream, seekTo, &frame, &time); @@ -380,11 +369,11 @@ BMediaTrack::SeekToTime(bigtime_t *inout_time, int32 flags) return result; } } - + *inout_time = time; fCurFrame = frame; fCurTime = time; - + PRINT(1, "BMediaTrack::SeekToTime finished, requested %.6f, result %.6f\n", seekTime / 1000000.0, *inout_time / 1000000.0); return B_OK; @@ -403,7 +392,7 @@ BMediaTrack::SeekToFrame(int64 *inout_frame, int32 flags) uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK) | B_MEDIA_SEEK_TO_FRAME; int64 seekFrame = *inout_frame; - + int64 frame = seekFrame; bigtime_t time = 0; status_t result = fExtractor->Seek(fStream, seekTo, &frame, &time); @@ -420,7 +409,7 @@ BMediaTrack::SeekToFrame(int64 *inout_frame, int32 flags) if (result != B_OK) { ERROR("BMediaTrack::SeekToFrame: decoder seek failed\n"); return result; - } + } if (fRawDecoder) { result = fRawDecoder->Seek(seekTo, seekFrame, &frame, 0, &time); @@ -429,7 +418,7 @@ BMediaTrack::SeekToFrame(int64 *inout_frame, int32 flags) return result; } } - + *inout_frame = frame; fCurFrame = frame; fCurTime = time; @@ -451,7 +440,7 @@ BMediaTrack::FindKeyFrameForTime(bigtime_t *inoutTime, int32 flags) const uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK) | B_MEDIA_SEEK_TO_TIME; - + int64 frame = 0; // dummy frame, will be ignored because of flags status_t result = fExtractor->FindKeyFrame(fStream, seekTo, &frame, @@ -478,7 +467,7 @@ BMediaTrack::FindKeyFrameForFrame(int64 *inoutFrame, uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK) | B_MEDIA_SEEK_TO_FRAME; - + bigtime_t time = 0; // dummy time, will be ignored because of flags status_t result = fExtractor->FindKeyFrame(fStream, seekTo, inoutFrame, @@ -525,81 +514,79 @@ BMediaTrack::ReadChunk(char **out_buffer, status_t -BMediaTrack::AddCopyright(const char *data) +BMediaTrack::AddCopyright(const char* copyright) { - UNIMPLEMENTED(); + if (fWriter == NULL) + return B_NO_INIT; - return B_OK; + return fWriter->SetCopyright(fStream, copyright); } status_t -BMediaTrack::AddTrackInfo(uint32 code, - const void *data, - size_t size, - uint32 flags) +BMediaTrack::AddTrackInfo(uint32 code, const void* data, size_t size, + uint32 flags) { - UNIMPLEMENTED(); + if (fWriter == NULL) + return B_NO_INIT; - return B_OK; + return fWriter->AddTrackInfo(fStream, code, data, size, flags); } status_t -BMediaTrack::WriteFrames(const void *data, - int32 num_frames, - int32 flags) +BMediaTrack::WriteFrames(const void* data, int32 frameCount, int32 flags) { - UNIMPLEMENTED(); + media_encode_info encodeInfo; + encodeInfo.flags = flags; - return B_OK; + return WriteFrames(data, frameCount, &encodeInfo); } status_t -BMediaTrack::WriteFrames(const void *data, - int64 num_frames, - media_encode_info *info) +BMediaTrack::WriteFrames(const void* data, int64 frameCount, + media_encode_info* info) { - UNIMPLEMENTED(); + if (fEncoder == NULL) + return B_NO_INIT; - return B_OK; + return fEncoder->Encode(data, frameCount, info); } status_t -BMediaTrack::WriteChunk(const void *data, - size_t size, - uint32 flags) +BMediaTrack::WriteChunk(const void* data, size_t size, uint32 flags) { - UNIMPLEMENTED(); + media_encode_info encodeInfo; + encodeInfo.flags = flags; - return B_OK; + return WriteChunk(data, size, &encodeInfo); } status_t -BMediaTrack::WriteChunk(const void *data, - size_t size, - media_encode_info *info) +BMediaTrack::WriteChunk(const void* data, size_t size, media_encode_info* info) { - UNIMPLEMENTED(); + if (fWriter == NULL) + return B_NO_INIT; - return B_OK; + return fWriter->WriteChunk(fStream, data, size, info); } status_t BMediaTrack::Flush() { - UNIMPLEMENTED(); + if (fWriter == NULL) + return B_NO_INIT; - return B_OK; + return fWriter->Flush(); } // deprecated BeOS R5 API -BParameterWeb * +BParameterWeb* BMediaTrack::Web() { UNIMPLEMENTED(); @@ -706,21 +693,20 @@ BMediaTrack::BMediaTrack(BPrivate::media::MediaExtractor *extractor, fExtractor = extractor; fStream = stream; fErr = B_OK; - + SetupWorkaround(); status_t ret = fExtractor->CreateDecoder(fStream, &fDecoder, &fMCI); if (ret != B_OK) { TRACE("BMediaTrack::BMediaTrack: Error: creating decoder failed: " "%s\n", strerror(ret)); - // we do not set fErr here, because ReadChunk should still work + // We do not set fErr here, because ReadChunk should still work. fDecoder = NULL; - return; } fCurFrame = 0; fCurTime = 0; - + // not used: fEncoder = NULL; fEncoderID = 0; @@ -729,16 +715,45 @@ BMediaTrack::BMediaTrack(BPrivate::media::MediaExtractor *extractor, BMediaTrack::BMediaTrack(BPrivate::media::MediaWriter* writer, - int32 stream_num, - media_format *in_format, - BPrivate::media::Encoder *encoder, - media_codec_info *mci) + int32 streamIndex, const media_format* format, + const media_codec_info* codecInfo) { - UNIMPLEMENTED(); + CALLED(); + + fWorkaroundFlags = 0; + fEncoder = NULL; + fEncoderID = -1; + // TODO: Not yet sure what this was needed for... + fWriter = writer; + fWriterFormat = *format; + fStream = streamIndex; + fErr = B_OK; + + SetupWorkaround(); + + if (codecInfo != NULL) { + status_t ret = fWriter->CreateEncoder(&fEncoder, codecInfo); + if (ret != B_OK) { + TRACE("BMediaTrack::BMediaTrack: Error: creating decoder failed: " + "%s\n", strerror(ret)); + // We do not set fErr here, because WriteChunk should still work. + fEncoder = NULL; + } else { + fMCI = *codecInfo; + fErr = fEncoder->SetUp(&fWriterFormat); + } + } + + // not used: + fCurFrame = 0; + fCurTime = 0; + fDecoder = NULL; + fRawDecoder = NULL; + fExtractor = NULL; } -// Does nothing, returns B_ERROR, for Zeta compatiblity only +// Does nothing, returns B_ERROR, for Zeta compatiblity only status_t BMediaTrack::ControlCodec(int32 selector, void *io_data, size_t size) { @@ -751,35 +766,37 @@ BMediaTrack::SetupWorkaround() { app_info ainfo; thread_info tinfo; - + get_thread_info(find_thread(0), &tinfo); be_roster->GetRunningAppInfo(tinfo.team, &ainfo); - + if (strcmp(ainfo.signature, "application/x-vnd.marcone-soundplay") == 0) { - fWorkaroundFlags = FORCE_RAW_AUDIO | FORCE_RAW_AUDIO_INT16_FORMAT | FORCE_RAW_AUDIO_HOST_ENDIAN; - printf("BMediaTrack::SetupWorkaround: SoundPlay workaround active\n"); + fWorkaroundFlags = FORCE_RAW_AUDIO | FORCE_RAW_AUDIO_INT16_FORMAT + | FORCE_RAW_AUDIO_HOST_ENDIAN; + printf("BMediaTrack::SetupWorkaround: SoundPlay workaround active\n"); } if (strcmp(ainfo.signature, "application/x-vnd.Be.MediaPlayer") == 0) { fWorkaroundFlags = IGNORE_ENCODED_AUDIO | IGNORE_ENCODED_VIDEO; - printf("BMediaTrack::SetupWorkaround: MediaPlayer workaround active\n"); + printf("BMediaTrack::SetupWorkaround: MediaPlayer workaround active\n"); } - + #if CONVERT_TO_INT32 // XXX test if (!(fWorkaroundFlags & FORCE_RAW_AUDIO_INT16_FORMAT)) fWorkaroundFlags |= FORCE_RAW_AUDIO_INT32_FORMAT; #endif } + bool BMediaTrack::SetupFormatTranslation(const media_format &from, media_format *to) { _plugin_manager.DestroyDecoder(fRawDecoder); fRawDecoder = NULL; -#ifdef TRACE_MEDIA_TRACK +#ifdef TRACE_MEDIA_TRACK char s[200]; string_for_format(from, s, sizeof(s)); - printf("BMediaTrack::SetupFormatTranslation: from: %s\n", s); + printf("BMediaTrack::SetupFormatTranslation: from: %s\n", s); #endif status_t res = _plugin_manager.CreateDecoder(&fRawDecoder, from); @@ -790,12 +807,16 @@ BMediaTrack::SetupFormatTranslation(const media_format &from, media_format *to) // XXX video? int buffer_size = from.u.raw_audio.buffer_size; - int frame_size = (from.u.raw_audio.format & 15) * from.u.raw_audio.channel_count; + int frame_size = (from.u.raw_audio.format & 15) + * from.u.raw_audio.channel_count; media_format notconstFrom = from; - ChunkProvider *chunkProvider = new(std::nothrow) RawDecoderChunkProvider(fDecoder, buffer_size, frame_size); + ChunkProvider *chunkProvider + = new(std::nothrow) RawDecoderChunkProvider(fDecoder, buffer_size, + frame_size); if (!chunkProvider) { - ERROR("BMediaTrack::SetupFormatTranslation: can't create chunk provider\n"); + ERROR("BMediaTrack::SetupFormatTranslation: can't create chunk " + "provider\n"); goto error; } fRawDecoder->SetChunkProvider(chunkProvider); @@ -806,20 +827,21 @@ BMediaTrack::SetupFormatTranslation(const media_format &from, media_format *to) goto error; } -#ifdef TRACE_MEDIA_TRACK +#ifdef TRACE_MEDIA_TRACK string_for_format(*to, s, sizeof(s)); - printf("BMediaTrack::SetupFormatTranslation: to: %s\n", s); + printf("BMediaTrack::SetupFormatTranslation: to: %s\n", s); #endif res = fRawDecoder->NegotiateOutputFormat(to); if (res != B_OK) { - ERROR("BMediaTrack::SetupFormatTranslation: NegotiateOutputFormat failed\n"); + ERROR("BMediaTrack::SetupFormatTranslation: NegotiateOutputFormat " + "failed\n"); goto error; } -#ifdef TRACE_MEDIA_TRACK +#ifdef TRACE_MEDIA_TRACK string_for_format(*to, s, sizeof(s)); - printf("BMediaTrack::SetupFormatTranslation: res: %s\n", s); + printf("BMediaTrack::SetupFormatTranslation: res: %s\n", s); #endif return true; diff --git a/src/kits/media/MediaWriter.cpp b/src/kits/media/MediaWriter.cpp index 1bb6dc8e54..32d83fbc02 100644 --- a/src/kits/media/MediaWriter.cpp +++ b/src/kits/media/MediaWriter.cpp @@ -18,6 +18,32 @@ #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), @@ -66,43 +92,6 @@ MediaWriter::GetFileFormatInfo(media_file_format* _fileFormat) const } -status_t -MediaWriter::WriteChunk(int32 streamIndex, const void* chunkBuffer, - size_t chunkSize, uint32 flags) -{ - 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, flags); -} - - -class MediaExtractorChunkWriter : public ChunkWriter { -public: - MediaExtractorChunkWriter(MediaWriter* writer, int32 streamIndex) - : - fWriter(writer), - fStreamIndex(streamIndex) - { - } - - virtual status_t WriteChunk(const void* chunkBuffer, size_t chunkSize, - uint32 flags) - { - return fWriter->WriteChunk(fStreamIndex, chunkBuffer, chunkSize, - flags); - } - -private: - MediaWriter* fWriter; - int32 fStreamIndex; -}; - - status_t MediaWriter::CreateEncoder(Encoder** _encoder, const media_codec_info* codecInfo, uint32 flags) @@ -149,3 +138,89 @@ MediaWriter::CreateEncoder(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); +} +