I have no fear of changing APIs. linking again

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5608 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
shatty 2003-12-07 13:25:03 +00:00
parent bc411e80d4
commit befdba918b
3 changed files with 118 additions and 50 deletions

View File

@ -10,6 +10,8 @@ Addon xvid_decoder : media plugins :
libxvidcore.a
;
SEARCH on libxvidcore.a += $(SUBDIR) ;
LinkSharedOSLibs xvid_decoder : be libmedia.so ;
SubInclude OBOS_TOP src add-ons media plugins xvid_decoder xvidcore ;

View File

@ -1,9 +1,11 @@
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <Autolock.h>
#include <DataIO.h>
#include <Locker.h>
#include <MediaFormats.h>
#include <MediaRoster.h>
#include "xvidDecoderPlugin.h"
#define TRACE_THIS 1
@ -13,9 +15,11 @@
#define TRACE(a...)
#endif
#define OUTPUT_BUFFER_SIZE (8 * 1024)
#define DECODE_BUFFER_SIZE (32 * 1024)
// this colorspace must be supported in translate_colorspace
#define DEFAULT_COLORSPACE B_RGB32
inline int translate_colorspace(enum color_space cs) {
switch (cs) {
case B_RGB32: return XVID_CSP_RGB32;
@ -38,10 +42,14 @@ inline int translate_colorspace(enum color_space cs) {
xvidDecoder::xvidDecoder()
{
memset(&fXvidDecoderParams, 0, sizeof(fXvidDecoderParams));
fXvidColorSpace = XVID_CSP_NULL;
fResidualBytes = 0;
fResidualBuffer = 0;
fDecodeBuffer = new uint8 [DECODE_BUFFER_SIZE];
fStartTime = 0;
fFrameSize = 0;
fBitRate = 0;
fOutputBufferSize = 0;
}
@ -55,7 +63,7 @@ xvidDecoder::~xvidDecoder()
status_t
xvidDecoder::Setup(media_format *ioEncodedFormat, media_format *ioDecodedFormat,
xvidDecoder::Setup(media_format *ioEncodedFormat,
const void *infoBuffer, int32 infoSize)
{
int xerr;
@ -66,33 +74,59 @@ xvidDecoder::Setup(media_format *ioEncodedFormat, media_format *ioDecodedFormat,
TRACE("xvidDecoder::Setup called twice\n");
return B_ERROR;
}
ioDecodedFormat->type = B_MEDIA_RAW_VIDEO;
ioDecodedFormat->u.raw_video = ioEncodedFormat->u.encoded_video.output;
fXvidDecoderParams.width = ioDecodedFormat->u.raw_video.display.line_width;
fXvidDecoderParams.height = ioDecodedFormat->u.raw_video.display.line_count;
fColorSpace = translate_colorspace(ioDecodedFormat->u.raw_video.display.format);
if (fColorSpace == XVID_CSP_NULL) {
TRACE("xvidDecoder: translate_colorspace(...) failed\n");
if (ioEncodedFormat->type != B_MEDIA_ENCODED_VIDEO) {
TRACE("xvidDecoder::Setup not called with encoded video");
return B_ERROR;
}
// save the extractor information for future reference
fOutput = ioEncodedFormat->u.encoded_video.output;
fBitRate = ioEncodedFormat->u.encoded_video.avg_bit_rate;
fFrameSize = ioEncodedFormat->u.encoded_video.frame_size;
// xvid can not detect the width and height so the extractor better give them to us
fXvidDecoderParams.width = fOutput.display.line_width;
fXvidDecoderParams.height = fOutput.display.line_count;
xerr = xvid_decore(NULL, XVID_DEC_CREATE, &fXvidDecoderParams, NULL);
if (xerr) {
TRACE("xvidDecoder: xvid_decore(...XVID_DEC_CREATE...) failed\n");
return B_ERROR;
}
/* ioDecodedFormat->u.raw_video.field_rate = ?
ioDecodedFormat->u.raw_video.interlace = 1;
ioDecodedFormat->u.raw_video.first_active = 0;
ioDecodedFormat->u.raw_video.last_active = ioDecodedFormat->display.line_count - 1;
ioDecodedFormat->u.raw_video.orientation = B_VIDEO_TOP_LEFT_RIGHT;
ioDecodedFormat->u.raw_video.pixel_width_aspect = 1;
ioDecodedFormat->u.raw_video.pixel_height_aspect = 1;
ioDecodedFormat->u.raw_video.display. ? =*/
fBytesPerRow = ioDecodedFormat->u.raw_video.display.bytes_per_row;
fFrameSize = ioDecodedFormat->u.raw_video.display.line_count * fBytesPerRow;
return B_OK;
}
status_t
xvidDecoder::NegotiateOutputFormat(media_format *ioDecodedFormat)
{
// BeBook says: The codec will find and return in ioFormat its best matching format
// => This means, we never return an error, and always change the format values
// that we don't support to something more applicable
ioDecodedFormat->type = B_MEDIA_RAW_VIDEO;
// 1st: the requested colorspace, 2nd: the extractor colorspace, 3rd: default
fXvidColorSpace = translate_colorspace(ioDecodedFormat->u.raw_video.display.format);
if (fXvidColorSpace == XVID_CSP_NULL) {
TRACE("xvidDecoder: translate_colorspace(...) failed: trying extractor colorspace\n");
fXvidColorSpace = translate_colorspace(fOutput.display.format);
if (fXvidColorSpace == XVID_CSP_NULL) {
TRACE("xvidDecoder: translate_colorspace(...) failed: using DEFAULT_COLORSPACE\n");
fOutput.display.format = DEFAULT_COLORSPACE;
fXvidColorSpace = translate_colorspace(fOutput.display.format);
assert(fXvidColorSpace != XVID_CSP_NULL);
}
} else {
fOutput.display.format = ioDecodedFormat->u.raw_video.display.format;
}
// xvid has nothing more to contribute about the output than what is already specified
ioDecodedFormat->u.raw_video = fOutput;
// setup rest of the needed variables
fOutputBufferSize = fOutput.display.line_count * fOutput.display.bytes_per_row;
return B_OK;
}
@ -128,7 +162,10 @@ xvidDecoder::Decode(void *buffer, int64 *frameCount,
media_header *mediaHeader, media_decode_info *info /* = 0 */)
{
uint8 * out_buffer = static_cast<uint8 *>(buffer);
int32 out_bytes_needed = OUTPUT_BUFFER_SIZE;
int32 out_bytes_needed = fOutputBufferSize;
mediaHeader->start_time = fStartTime;
//TRACE("xvidDecoder: Decoding start time %.6f\n", fStartTime / 1000000.0);
while (out_bytes_needed > 0) {
if (fResidualBytes) {
@ -138,37 +175,58 @@ xvidDecoder::Decode(void *buffer, int64 *frameCount,
fResidualBytes -= bytes;
out_buffer += bytes;
out_bytes_needed -= bytes;
fStartTime += (bigtime_t) (((1000000LL * (bytes / fFrameSize))
/ fOutput.interlace)
/ fOutput.field_rate) ;
//TRACE("xvidDecoder: fStartTime inc'd to %.6f\n", fStartTime / 1000000.0);
continue;
}
void *chunkBuffer;
int32 chunkSize;
if (B_OK != GetNextChunk(&chunkBuffer, &chunkSize, mediaHeader)) {
TRACE("xvidDecoder::Decode: GetNextChunk failed\n");
return B_ERROR;
}
XVID_DEC_FRAME xframe;
xframe.bitstream = chunkBuffer;
xframe.length = chunkSize;
xframe.image = out_buffer;
xframe.stride = fBytesPerRow;
xframe.colorspace = fColorSpace;
int xerr;
xerr = xvid_decore(fXvidDecoderParams.handle,XVID_DEC_DECODE,&xframe,NULL);
if (xerr) {
TRACE("xvidDecoder::Decode: xvid_decore returned an error\n");
return B_ERROR;
}
//printf("xvidDecoder::Decode: decoded %d bytes into %d bytes\n",chunkSize, outsize);
fResidualBuffer = static_cast<uint8 *>(xframe.bitstream);
fResidualBytes = xframe.length;
if (B_OK != DecodeNextChunk())
break;
}
*frameCount = OUTPUT_BUFFER_SIZE / fFrameSize;
*frameCount = (fOutputBufferSize - out_bytes_needed) / fFrameSize;
// XXX this doesn't guarantee that we always return B_LAST_BUFFER_ERROR bofore returning B_ERROR
return (out_bytes_needed == 0) ? B_OK : (out_bytes_needed == fOutputBufferSize) ? B_ERROR : B_LAST_BUFFER_ERROR;
}
status_t
xvidDecoder::DecodeNextChunk()
{
void *chunkBuffer;
int32 chunkSize;
media_header mh;
if (B_OK != GetNextChunk(&chunkBuffer, &chunkSize, &mh)) {
TRACE("xvidDecoder::Decode: GetNextChunk failed\n");
return B_ERROR;
}
fStartTime = mh.start_time;
//TRACE("xvidDecoder: fStartTime reset to %.6f\n", fStartTime / 1000000.0);
XVID_DEC_FRAME xframe;
xframe.bitstream = chunkBuffer;
xframe.length = chunkSize;
xframe.image = fDecodeBuffer;
xframe.stride = fOutput.display.bytes_per_row;
xframe.colorspace = fXvidColorSpace;
int xerr;
xerr = xvid_decore(fXvidDecoderParams.handle,XVID_DEC_DECODE,&xframe,NULL);
if (xerr) {
TRACE("xvidDecoder::Decode: xvid_decore returned an error\n");
return B_ERROR;
}
//printf("xvidDecoder::Decode: decoded %d bytes into %d bytes\n",chunkSize, outsize);
fResidualBuffer = static_cast<uint8 *>(xframe.bitstream);
fResidualBytes = xframe.length;
return B_OK;
}

View File

@ -8,9 +8,11 @@ public:
xvidDecoder();
~xvidDecoder();
status_t Setup(media_format *ioEncodedFormat, media_format *ioDecodedFormat,
status_t Setup(media_format *ioEncodedFormat,
const void *infoBuffer, int32 infoSize);
status_t NegotiateOutputFormat(media_format *ioDecodedFormat);
status_t Seek(uint32 seekTo,
int64 seekFrame, int64 *frame,
bigtime_t seekTime, bigtime_t *time);
@ -18,14 +20,20 @@ public:
status_t Decode(void *buffer, int64 *frameCount,
media_header *mediaHeader, media_decode_info *info);
status_t DecodeNextChunk();
private:
XVID_DEC_PARAM fXvidDecoderParams;
int fXvidColorSpace;
struct media_raw_video_format fOutput;
int32 fResidualBytes;
uint8 * fResidualBuffer;
uint8 * fDecodeBuffer;
int32 fFrameSize;
uint32 fBytesPerRow;
int fColorSpace;
bigtime_t fStartTime;
int fFrameSize;
float fBitRate;
int fOutputBufferSize;
};