When the decoder doesn't support the requested format, the raw decoder is utilized

to provide a format conversion to the requested raw format.
Added a few workarounds for applications that don't requst the required format
but instead assume to get a specific one.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6815 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
beveloper
2004-02-29 18:53:57 +00:00
parent 94722b265c
commit bac2b3f15c
2 changed files with 276 additions and 9 deletions
+11 -3
View File
@@ -81,7 +81,7 @@ public:
// The data returned through ReadFrames() will be in the format that's
// returned by this function.
status_t DecodedFormat(media_format *inout_format);
status_t DecodedFormat(media_format *inout_format, int32 flags = 0);
// CountFrames and Duration return the total number of frame and the
// total duration (expressed in microseconds) of a track.
@@ -206,9 +206,16 @@ private:
BPrivate::media::Encoder *encoder,
media_codec_info *mci);
#ifdef __BUILDING_MEDIA_TRACK_CPP
status_t DecodedFormat(media_format *inout_format);
#endif
void SetupWorkaround();
bool SetupFormatTranslation(const media_format &from, media_format *to);
status_t fErr;
BPrivate::media::Decoder *fDecoder;
int32 __unused__fDecoderID;
BPrivate::media::Decoder *fRawDecoder;
BPrivate::media::MediaExtractor *fExtractor;
int32 fStream;
@@ -221,7 +228,8 @@ private:
int32 fEncoderID;
BPrivate::MediaWriter *fWriter;
media_format fWriterFormat;
void *__unused__fExtractorCookie;
uint32 fWorkaroundFlags;
protected:
int32 EncoderID() { return fEncoderID; };
+265 -6
View File
@@ -3,13 +3,49 @@
* FILE: MediaTrack.cpp
* DESCR:
***********************************************************************/
#define __BUILDING_MEDIA_TRACK_CPP
#include <MediaTrack.h>
#include <Roster.h>
#include <string.h>
#include "MediaExtractor.h"
#include "PluginManager.h"
#include "ReaderPlugin.h"
#include "debug.h"
#define CONVERT_TO_INT32 1 // XXX test! this triggers a few bugs!
// flags used for workarounds
enum {
FORCE_RAW_AUDIO = 0x0001,
FORCE_RAW_VIDEO = 0x0002,
FORCE_RAW_AUDIO_INT16_FORMAT = 0x0010,
FORCE_RAW_AUDIO_INT32_FORMAT = 0x0020,
FORCE_RAW_AUDIO_FLOAT_FORMAT = 0x0040,
FORCE_RAW_AUDIO_HOST_ENDIAN = 0x0100,
IGNORE_ENCODED_AUDIO = 0x1000,
IGNORE_ENCODED_VIDEO = 0x2000,
};
#define B_MEDIA_DISABLE_FORMAT_TRANSLATION 0x4000 // XXX move this (after name change?) to MediaDefs.h
class RawDecoderChunkProvider : public ChunkProvider
{
public:
RawDecoderChunkProvider(Decoder *decoder, int buffer_size, int frame_size);
virtual ~RawDecoderChunkProvider();
status_t GetNextChunk(void **chunkBuffer, int32 *chunkSize, media_header *mediaHeader);
private:
Decoder *fDecoder;
void *fBuffer;
int fBufferSize;
int fFrameSize;
};
/*************************************************************
* protected BMediaTrack
*************************************************************/
@@ -17,6 +53,8 @@
BMediaTrack::~BMediaTrack()
{
CALLED();
if (fRawDecoder)
_DestroyDecoder(fRawDecoder);
if (fDecoder)
_DestroyDecoder(fDecoder);
}
@@ -58,12 +96,23 @@ BMediaTrack::EncodedFormat(media_format *out_format) const
*out_format = *fExtractor->EncodedFormat(fStream);
char s[200];
string_for_format(*out_format, s, sizeof(s));
printf("BMediaTrack::EncodedFormat: %s\n", s);
return B_OK;
}
status_t
BMediaTrack::DecodedFormat(media_format *inout_format)
{
return DecodedFormat(inout_format, 0);
}
status_t
BMediaTrack::DecodedFormat(media_format *inout_format, int32 flags)
{
CALLED();
if (!inout_format)
@@ -71,7 +120,83 @@ BMediaTrack::DecodedFormat(media_format *inout_format)
if (!fExtractor || !fDecoder)
return B_NO_INIT;
return fDecoder->NegotiateOutputFormat(inout_format);
if (fRawDecoder) {
_DestroyDecoder(fRawDecoder);
fRawDecoder = 0;
}
char s[200];
string_for_format(*inout_format, s, sizeof(s));
printf("BMediaTrack::DecodedFormat: req1: %s\n", s);
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;
}
if ((fWorkaroundFlags & FORCE_RAW_VIDEO) || ((fWorkaroundFlags & IGNORE_ENCODED_VIDEO) && inout_format->type == B_MEDIA_ENCODED_VIDEO)) {
inout_format->type = B_MEDIA_RAW_VIDEO;
inout_format->u.raw_video = media_raw_video_format::wildcard;
}
if (inout_format->type == B_MEDIA_RAW_AUDIO) {
if (fWorkaroundFlags & FORCE_RAW_AUDIO_HOST_ENDIAN)
inout_format->u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN;
if (fWorkaroundFlags & FORCE_RAW_AUDIO_INT16_FORMAT)
inout_format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT;
if (fWorkaroundFlags & FORCE_RAW_AUDIO_INT32_FORMAT)
inout_format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_INT;
if (fWorkaroundFlags & FORCE_RAW_AUDIO_FLOAT_FORMAT)
inout_format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT;
}
string_for_format(*inout_format, s, sizeof(s));
printf("BMediaTrack::DecodedFormat: req2: %s\n", s);
media_format requested_format = *inout_format;
status_t res;
res = fDecoder->NegotiateOutputFormat(inout_format);
string_for_format(*inout_format, s, sizeof(s));
printf("BMediaTrack::DecodedFormat: nego: %s\n", s);
if (inout_format->type == 0)
debugger("Decoder didn't set output format type");
if (inout_format->type == B_MEDIA_RAW_AUDIO) {
if (inout_format->u.raw_audio.byte_order == 0)
debugger("Decoder didn't set raw audio output byte order");
if (inout_format->u.raw_audio.format == 0)
debugger("Decoder didn't set raw audio output sample format");
if (inout_format->u.raw_audio.buffer_size <= 0)
debugger("Decoder didn't set raw audio output buffer size");
}
if (inout_format->type == B_MEDIA_RAW_VIDEO) {
if (inout_format->u.raw_video.display.format == 0)
debugger("Decoder didn't set raw video output color space");
if (inout_format->u.raw_video.display.line_width == 0)
debugger("Decoder didn't set raw video output line_width");
if (inout_format->u.raw_video.display.line_count == 0)
debugger("Decoder didn't set raw video output line_count");
if (inout_format->u.raw_video.display.bytes_per_row == 0)
debugger("Decoder didn't set raw video output bytes_per_row");
}
if (0 == (flags & B_MEDIA_DISABLE_FORMAT_TRANSLATION)) {
if (requested_format.type == B_MEDIA_RAW_AUDIO
&& inout_format->type == B_MEDIA_RAW_AUDIO
&& requested_format.u.raw_audio.format != 0
&& requested_format.u.raw_audio.format != inout_format->u.raw_audio.format) {
if (SetupFormatTranslation(*inout_format, &requested_format)) {
*inout_format = requested_format;
}
}
}
// string_for_format(*inout_format, s, sizeof(s));
// printf("BMediaTrack::DecodedFormat: res: %s\n", s);
return res;
}
@@ -79,7 +204,9 @@ int64
BMediaTrack::CountFrames() const
{
CALLED();
return fExtractor ? fExtractor->CountFrames(fStream) : 0;
int64 frames = fExtractor ? fExtractor->CountFrames(fStream) : 0;
printf("BMediaTrack::CountFrames: %Ld\n", frames);
return frames;
}
@@ -87,7 +214,9 @@ bigtime_t
BMediaTrack::Duration() const
{
CALLED();
return fExtractor ? fExtractor->Duration(fStream) : 0;
bigtime_t duration = fExtractor ? fExtractor->Duration(fStream) : 0;
printf("BMediaTrack::Duration: %Ld\n", duration);
return duration;
}
@@ -130,8 +259,11 @@ BMediaTrack::ReadFrames(void *out_buffer,
media_header header;
memset(&header, 0, sizeof(header)); // always clear it first, as the decoder doesn't set all fields
result = fDecoder->Decode(out_buffer, out_frameCount, &header, info);
if (fRawDecoder)
result = fRawDecoder->Decode(out_buffer, out_frameCount, &header, info);
else
result = fDecoder->Decode(out_buffer, out_frameCount, &header, info);
if (result == B_OK) {
fCurFrame += *out_frameCount;
fCurTime = header.start_time;
@@ -141,6 +273,9 @@ BMediaTrack::ReadFrames(void *out_buffer,
}
if (mh)
*mh = header;
printf("BMediaTrack::ReadFrames: %Ld frames, start-time %Ld\n", *out_frameCount, header.start_time);
return result;
}
@@ -182,12 +317,20 @@ BMediaTrack::SeekToTime(bigtime_t *inout_time,
printf("BMediaTrack::SeekToTime: extractor seek failed\n");
return result;
}
result = fDecoder->Seek(seekTo, 0, &frame, seekTime, &time);
if (result != B_OK) {
printf("BMediaTrack::SeekToTime: decoder seek failed\n");
return result;
}
if (fRawDecoder) {
result = fRawDecoder->Seek(seekTo, 0, &frame, seekTime, &time);
if (result != B_OK) {
printf("BMediaTrack::SeekToTime: raw decoder seek failed\n");
return result;
}
}
*inout_time = time;
fCurFrame = frame;
@@ -231,6 +374,14 @@ BMediaTrack::SeekToFrame(int64 *inout_frame,
return result;
printf("BMediaTrack::SeekToFrame: decoder seek failed\n");
}
if (fRawDecoder) {
result = fRawDecoder->Seek(seekTo, seekFrame, &frame, 0, &time);
if (result != B_OK) {
printf("BMediaTrack::SeekToFrame: raw decoder seek failed\n");
return result;
}
}
*inout_frame = frame;
fCurFrame = frame;
@@ -453,11 +604,16 @@ BMediaTrack::BMediaTrack(BPrivate::media::MediaExtractor *extractor,
int32 stream)
{
CALLED();
fWorkaroundFlags = 0;
fRawDecoder = 0;
fExtractor = extractor;
fStream = stream;
fErr = B_OK;
SetupWorkaround();
if (fExtractor->CreateDecoder(fStream, &fDecoder, &fMCI) != B_OK) {
ERROR("BMediaTrack::BMediaTrack: Error: creating decoder failed\n");
// we do not set fErr here, because ReadChunk should still work
fDecoder = 0;
return;
@@ -482,6 +638,78 @@ BMediaTrack::BMediaTrack(BPrivate::MediaWriter *writer,
UNIMPLEMENTED();
}
void
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");
}
if (strcmp(ainfo.signature, "application/x-vnd.Be.MediaPlayer") == 0) {
fWorkaroundFlags = IGNORE_ENCODED_AUDIO | IGNORE_ENCODED_VIDEO;
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)
{
char s[200];
status_t res;
string_for_format(from, s, sizeof(s));
printf("BMediaTrack::SetupFormatTranslation: from: %s\n", s);
res = _CreateDecoder(&fRawDecoder, from);
if (res != B_OK) {
printf("BMediaTrack::SetupFormatTranslation: _CreateDecoder failed\n");
return false;
}
// 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;
fRawDecoder->Setup(new RawDecoderChunkProvider(fDecoder, buffer_size, frame_size));
media_format from_temp = from;
res = fRawDecoder->Setup(&from_temp, 0, 0);
if (res != B_OK) {
printf("BMediaTrack::SetupFormatTranslation: Setup failed\n");
goto error;
}
string_for_format(*to, s, sizeof(s));
printf("BMediaTrack::SetupFormatTranslation: to: %s\n", s);
res = fRawDecoder->NegotiateOutputFormat(to);
if (res != B_OK) {
printf("BMediaTrack::SetupFormatTranslation: NegotiateOutputFormat failed\n");
goto error;
}
string_for_format(*to, s, sizeof(s));
printf("BMediaTrack::SetupFormatTranslation: res: %s\n", s);
return true;
error:
_DestroyDecoder(fRawDecoder);
fRawDecoder = 0;
return false;
}
/*
// unimplemented
BMediaTrack::BMediaTrack()
@@ -538,3 +766,34 @@ status_t BMediaTrack::_Reserved_BMediaTrack_45(int32 arg, ...) { return B_ERROR;
status_t BMediaTrack::_Reserved_BMediaTrack_46(int32 arg, ...) { return B_ERROR; }
status_t BMediaTrack::_Reserved_BMediaTrack_47(int32 arg, ...) { return B_ERROR; }
RawDecoderChunkProvider::RawDecoderChunkProvider(Decoder *decoder, int buffer_size, int frame_size)
{
printf("RawDecoderChunkProvider: buffer_size %d, frame_size %d\n", buffer_size, frame_size);
fDecoder = decoder;
fFrameSize = frame_size;
fBufferSize = buffer_size;
fBuffer = malloc(buffer_size);
}
RawDecoderChunkProvider::~RawDecoderChunkProvider()
{
free(fBuffer);
}
status_t
RawDecoderChunkProvider::GetNextChunk(void **chunkBuffer, int32 *chunkSize,
media_header *mediaHeader)
{
int64 frames;
media_decode_info info;
status_t res = fDecoder->Decode(fBuffer, &frames, mediaHeader, &info);
if (res == B_OK) {
*chunkBuffer = fBuffer;
*chunkSize = frames * fFrameSize;
printf("RawDecoderChunkProvider::GetNextChunk, %Ld frames, %ld bytes, start-time %Ld\n", frames, *chunkSize, mediaHeader->start_time);
} else {
printf("RawDecoderChunkProvider::GetNextChunk failed\n");
}
return res;
}