* Writer::WriteChunk() takes media_encode_info* instead of flags.

* Improved Encoder API towards what we need for the get_next_encoder() variants
  and the BMediaTrack API.
* Implemented the rest of MediaWriter. Still undecided what to make of
  AddTrackInfo(). BMediaEncoder has that as well, which hints that this is
  something the Encoder needs to support. But it could also be that this is
  only possible to support in Writer.
* Wired a lot of previously unimplemented methods in BMediaFile and BMediaTrack
  needed for write support. If I have not overlooked anything, only the
  parameter stuff is still unimplemented now.

This is all untested, since the FFMpeg Encoder and Writer are still only stubs.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32013 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2009-07-31 10:46:58 +00:00
parent 23046a3935
commit fa770e4c84
13 changed files with 450 additions and 235 deletions

View File

@ -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 <image.h>
#include <List.h>
#include <MediaDefs.h>
@ -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&);

View File

@ -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:

View File

@ -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);

View File

@ -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 {

View File

@ -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;

View File

@ -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)

View File

@ -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:
};

View File

@ -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;
}

View File

@ -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;

View File

@ -1,4 +1,4 @@
/*
/*
* Copyright 2009, Stephan Aßmus <superstippi@gmx.de>. 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);
}

View File

@ -1,18 +1,23 @@
/*
* Copyright (c) 2002-2004, Marcus Overhagen <marcus@overhagen.de>
* All rights reserved. Distributed under the terms of the MIT License.
* Copyright 2009, Stephan Aßmus <superstippi@gmx.de>
* Copyright 2002-2004, Marcus Overhagen <marcus@overhagen.de>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#include <MediaFile.h>
#include <new>
#include <stdlib.h>
#include <string.h>
#include <MediaTrack.h>
#include <File.h>
#include <MediaTrack.h>
#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;
}

View File

@ -1,37 +1,26 @@
/*
* Copyright (c) 2002-2007, Marcus Overhagen <marcus@overhagen.de>
* 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 <superstippi@gmx.de>
* Copyright 2002-2007, Marcus Overhagen <marcus@overhagen.de>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#include <MediaTrack.h>
#include <Roster.h>
#include <new>
#include <string.h>
#include <stdlib.h>
#include <new>
#include "MediaExtractor.h"
#include "PluginManager.h"
#include <Roster.h>
#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;

View File

@ -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);
}