* Cleanup and improvements in the debug output

* Handles wrapping of the chunk buffer for the case that we need to read
  additional chunk data, but still need the data from the last chunk
  buffer as well.
* Don't skip the very first frame when calculating the timing.
* Includes some new code to handle seeking internally, but it is currently
  disabled and incomplete.
* Prepared to recover from floating point exceptions generated in some rare 
  situations by xvid, but we are currently missing fenv.h in our public POSIX
  headers, so it is disabled.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24945 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2008-04-12 13:24:33 +00:00
parent b6d44561ff
commit 2082f2d5c1
3 changed files with 199 additions and 79 deletions
@@ -13,4 +13,4 @@ Addon xvid.decoder :
libmedia.so libmedia.so
; ;
#SubInclude HAIKU_TOP src add-ons media plugins xvid_decoder libxvid ; #SubIncludeGPL HAIKU_TOP src add-ons media plugins xvid_decoder libxvid ;
@@ -18,10 +18,17 @@
* *
*/ */
#define DEBUG 0 #define DEBUG 0
#define PROPER_SEEKING 0
#define PRINT_FOURCC 0
#define MIN_USEFUL_BYTES 1
#include "XvidDecoder.h" #include "XvidDecoder.h"
//#include <fenv.h>
#include <new> #include <new>
#include <setjmp.h>
#include <signal.h>
#include <string.h> #include <string.h>
#include <ByteOrder.h> #include <ByteOrder.h>
@@ -141,9 +148,6 @@ print_media_decode_info(media_decode_info *info)
// #pragma mark - // #pragma mark -
#define MIN_USEFUL_BYTES 1
XvidDecoder::XvidDecoder() XvidDecoder::XvidDecoder()
: Decoder() : Decoder()
, fInputFormat() , fInputFormat()
@@ -156,6 +160,7 @@ XvidDecoder::XvidDecoder()
, fIndexInCodecTable(-1) , fIndexInCodecTable(-1)
, fChunkBuffer(NULL) , fChunkBuffer(NULL)
, fWrappedChunkBuffer(NULL)
, fChunkBufferHandle(NULL) , fChunkBufferHandle(NULL)
, fChunkBufferSize(0) , fChunkBufferSize(0)
, fLeftInChunkBuffer(0) , fLeftInChunkBuffer(0)
@@ -167,6 +172,7 @@ XvidDecoder::XvidDecoder()
XvidDecoder::~XvidDecoder() XvidDecoder::~XvidDecoder()
{ {
_XvidUninit(); _XvidUninit();
delete[] fWrappedChunkBuffer;
} }
@@ -202,7 +208,7 @@ XvidDecoder::Setup(media_format* inputFormat, const void* inInfo,
if (inputFormat->type != B_MEDIA_ENCODED_VIDEO) if (inputFormat->type != B_MEDIA_ENCODED_VIDEO)
return B_BAD_VALUE; return B_BAD_VALUE;
PRINT(("XvidDecoder::Sniff()\n")); // PRINT(("%p->XvidDecoder::Sniff()\n", this));
//#if DEBUG //#if DEBUG
// char buffer[1024]; // char buffer[1024];
@@ -235,18 +241,28 @@ XvidDecoder::Setup(media_format* inputFormat, const void* inInfo,
codecID = descr.u.quicktime.codec; codecID = descr.u.quicktime.codec;
familyID = B_QUICKTIME_FORMAT_FAMILY; familyID = B_QUICKTIME_FORMAT_FAMILY;
#if DEBUG #if PRINT_FOURCC
uint32 bigEndianID = B_HOST_TO_BENDIAN_INT32(codecID); uint32 bigEndianID = B_HOST_TO_BENDIAN_INT32(codecID);
PRINT(("XvidDecoder::Sniff() - QT 4CC: %.4s\n", (const char*)&bigEndianID)); printf("%p->XvidDecoder::Setup() - QT 4CC: %.4s\n", this,
(const char*)&bigEndianID);
#endif #endif
} else if (formats.GetCodeFor(*inputFormat, B_AVI_FORMAT_FAMILY, } else if (formats.GetCodeFor(*inputFormat, B_AVI_FORMAT_FAMILY,
&descr) == B_OK) { &descr) == B_OK) {
codecID = descr.u.avi.codec; codecID = descr.u.avi.codec;
familyID = B_AVI_FORMAT_FAMILY; familyID = B_AVI_FORMAT_FAMILY;
#if DEBUG #if PRINT_FOURCC
uint32 bigEndianID = B_HOST_TO_BENDIAN_INT32(codecID); uint32 bigEndianID = B_HOST_TO_BENDIAN_INT32(codecID);
PRINT(("XvidDecoder::Sniff() - AVI 4CC: %.4s\n", (const char*)&codecID)); printf("%p->XvidDecoder::Sniff() - AVI 4CC: %.4s\n", this,
(const char*)&bigEndianID);
#endif
} else if (formats.GetCodeFor(*inputFormat, B_MPEG_FORMAT_FAMILY,
&descr) == B_OK) {
codecID = descr.u.mpeg.id;
familyID = B_MPEG_FORMAT_FAMILY;
#if PRINT_FOURCC
printf("%p->XvidDecoder::Setup() - MPEG ID: %ld\n", this, codecID);
#endif #endif
} }
} }
@@ -257,14 +273,18 @@ XvidDecoder::Setup(media_format* inputFormat, const void* inInfo,
for (int32 i = 0; i < gSupportedCodecsCount; i++) { for (int32 i = 0; i < gSupportedCodecsCount; i++) {
if (gCodecTable[i].family == familyID if (gCodecTable[i].family == familyID
&& gCodecTable[i].fourcc == codecID) { && gCodecTable[i].fourcc == codecID) {
PRINT(("XvidDecoder::Sniff() - found codec in the table at %ld.\n", i)); PRINT(("%p->XvidDecoder::Setup() - found codec in the table "
"at %ld.\n", this, i));
fIndexInCodecTable = i; fIndexInCodecTable = i;
fInputFormat = *inputFormat; fInputFormat = *inputFormat;
return B_OK; return B_OK;
} }
} }
PRINT(("XvidDecoder::Sniff() - no matching codec found in the table.\n")); #if PRINT_FOURCC
printf("%p->XvidDecoder::Setup() - no matching codec found in the "
"table.\n", this);
#endif
return B_ERROR; return B_ERROR;
} }
@@ -273,13 +293,14 @@ XvidDecoder::Setup(media_format* inputFormat, const void* inInfo,
status_t status_t
XvidDecoder::NegotiateOutputFormat(media_format* _inoutFormat) XvidDecoder::NegotiateOutputFormat(media_format* _inoutFormat)
{ {
PRINT((" XvidDecoder::NegotiateOutputFormat()\n")); PRINT(("%p->XvidDecoder::NegotiateOutputFormat()\n", this));
if (_inoutFormat == NULL) if (_inoutFormat == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
#if DEBUG #if DEBUG
char buffer[1024]; char buffer[1024];
buffer[0] = 0;
if (string_for_format(*_inoutFormat, buffer, sizeof(buffer)) == B_OK) if (string_for_format(*_inoutFormat, buffer, sizeof(buffer)) == B_OK)
PRINT((" _inoutFormat = %s\n", buffer)); PRINT((" _inoutFormat = %s\n", buffer));
#endif #endif
@@ -353,8 +374,8 @@ XvidDecoder::NegotiateOutputFormat(media_format* _inoutFormat)
_inoutFormat->deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS; _inoutFormat->deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS;
#if DEBUG #if DEBUG
string_for_format(*_inoutFormat, buffer, sizeof(buffer)); if (string_for_format(*_inoutFormat, buffer, sizeof(buffer)) == B_OK)
PRINT(("XvidDecoder: out_format=%s\n", buffer)); PRINT(("%p->XvidDecoder: out_format=%s\n", this, buffer));
#endif #endif
return _XvidInit(true, 0) == 0 ? B_OK : B_ERROR; return _XvidInit(true, 0) == 0 ? B_OK : B_ERROR;
@@ -362,18 +383,20 @@ XvidDecoder::NegotiateOutputFormat(media_format* _inoutFormat)
status_t status_t
XvidDecoder::Decode(void* outBuffer, int64 *outFrameCount, media_header *mh, XvidDecoder::Decode(void* outBuffer, int64* outFrameCount, media_header* mh,
media_decode_info *info) media_decode_info* info)
{ {
if (outBuffer == NULL || outFrameCount == NULL || mh == NULL) if (outBuffer == NULL || outFrameCount == NULL || mh == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
PRINT(("XvidDecoder::Decode()\n")); // PRINT((%p->"XvidDecoder::Decode()\n", this));
*outFrameCount = 0;
// are we in a hurry ? // are we in a hurry ?
bool hurryUp = (!info || (info->time_to_decode > 0)) ? false : true; bool hurryUp = (!info || (info->time_to_decode > 0)) ? false : true;
mh->type = B_MEDIA_RAW_VIDEO; mh->type = B_MEDIA_UNKNOWN_TYPE;
mh->start_time = 0; mh->start_time = 0;
mh->size_used = 0; mh->size_used = 0;
mh->file_pos = 0; mh->file_pos = 0;
@@ -394,16 +417,58 @@ XvidDecoder::Decode(void* outBuffer, int64 *outFrameCount, media_header *mh,
do { do {
if (fLeftInChunkBuffer <= MIN_USEFUL_BYTES) { if (fLeftInChunkBuffer <= MIN_USEFUL_BYTES) {
uint8* leftOverBuffer = NULL;
size_t leftOverBufferSize = 0;
if (fLeftInChunkBuffer > 0) {
// we need to wrap the chunk buffer
// create a temporary buffer to hold the remaining data
leftOverBufferSize = fLeftInChunkBuffer;
leftOverBuffer = new (nothrow) uint8[leftOverBufferSize];
if (!leftOverBuffer)
ret = B_NO_MEMORY;
else {
memcpy(leftOverBuffer, fChunkBufferHandle,
leftOverBufferSize);
}
}
// we don't need the previous wrapped buffer anymore in
// case we had it
delete[] fWrappedChunkBuffer;
fWrappedChunkBuffer = NULL;
// read new data // read new data
ret = GetNextChunk(&fChunkBuffer, &fChunkBufferSize, mh); if (ret >= B_OK)
ret = GetNextChunk(&fChunkBuffer, &fChunkBufferSize, mh);
if (ret >= B_OK) { if (ret >= B_OK) {
fLeftInChunkBuffer = fChunkBufferSize; if (leftOverBuffer) {
fChunkBufferHandle = (const char*)fChunkBuffer; fWrappedChunkBuffer = new (nothrow) uint8[fChunkBufferSize
} else { + leftOverBufferSize];
if (!fWrappedChunkBuffer)
ret = B_NO_MEMORY;
else {
// copy the left over buffer to the beginning of the
// wrapped chunk buffer
memcpy(fWrappedChunkBuffer, leftOverBuffer,
leftOverBufferSize);
// copy the new chunk buffer after that
memcpy(fWrappedChunkBuffer + leftOverBufferSize,
fChunkBuffer, fChunkBufferSize);
fChunkBufferSize += leftOverBufferSize;
fLeftInChunkBuffer = fChunkBufferSize;
fChunkBufferHandle = (const char*)fWrappedChunkBuffer;
}
} else {
fLeftInChunkBuffer = fChunkBufferSize;
fChunkBufferHandle = (const char*)fChunkBuffer;
}
}
if (ret < B_OK) {
fChunkBufferSize = 0; fChunkBufferSize = 0;
fChunkBuffer = NULL; fChunkBuffer = NULL;
fChunkBufferHandle = NULL; fChunkBufferHandle = NULL;
} }
delete[] leftOverBuffer;
} }
// Check if there is a negative number of useful bytes left in buffer // Check if there is a negative number of useful bytes left in buffer
@@ -417,8 +482,9 @@ XvidDecoder::Decode(void* outBuffer, int64 *outFrameCount, media_header *mh,
// This loop is needed to handle VOL/NVOP reading // This loop is needed to handle VOL/NVOP reading
do { do {
// Decode frame // Decode frame
int usedBytes = _XvidDecode((uchar*)fChunkBufferHandle, (uchar*)outBuffer, int usedBytes = _XvidDecode((uchar*)fChunkBufferHandle,
fLeftInChunkBuffer, &xvidDecoderStats, hurryUp); (uchar*)outBuffer, fLeftInChunkBuffer, &xvidDecoderStats,
hurryUp);
// Resize image buffer if needed // Resize image buffer if needed
if (xvidDecoderStats.type == XVID_TYPE_VOL) { if (xvidDecoderStats.type == XVID_TYPE_VOL) {
@@ -429,9 +495,10 @@ XvidDecoder::Decode(void* outBuffer, int64 *outFrameCount, media_header *mh,
< xvidDecoderStats.data.vol.width < xvidDecoderStats.data.vol.width
* xvidDecoderStats.data.vol.height) { * xvidDecoderStats.data.vol.height) {
PRINT(("XvidDecoder::Decode() - image size changed!\n", fprintf(stderr, "XvidDecoder::Decode() - image size "
"changed: %dx%d\n",
xvidDecoderStats.data.vol.width, xvidDecoderStats.data.vol.width,
xvidDecoderStats.data.vol.height)); xvidDecoderStats.data.vol.height);
return B_ERROR; return B_ERROR;
} }
@@ -443,8 +510,9 @@ XvidDecoder::Decode(void* outBuffer, int64 *outFrameCount, media_header *mh,
fLeftInChunkBuffer -= usedBytes; fLeftInChunkBuffer -= usedBytes;
} }
PRINT(("XvidDecoder::Decode() - chunk %d: %d bytes consumed, " // PRINT((%p->"XvidDecoder::Decode() - chunk %d: %d bytes consumed, "
"%d bytes in buffer\n", chunk++, usedBytes, fLeftInChunkBuffer)); // "%d bytes in buffer\n", this, chunk++, usedBytes,
// fLeftInChunkBuffer));
} while (xvidDecoderStats.type <= 0 } while (xvidDecoderStats.type <= 0
&& fLeftInChunkBuffer > MIN_USEFUL_BYTES); && fLeftInChunkBuffer > MIN_USEFUL_BYTES);
@@ -458,26 +526,34 @@ XvidDecoder::Decode(void* outBuffer, int64 *outFrameCount, media_header *mh,
} while (fLeftInChunkBuffer > MIN_USEFUL_BYTES || ret >= B_OK); } while (fLeftInChunkBuffer > MIN_USEFUL_BYTES || ret >= B_OK);
if (ret != B_OK) if (ret != B_OK) {
PRINT(("%p->XvidDecoder::Decode() - error: %s\n", this,
strerror(ret)));
return ret; return ret;
}
mh->type = B_MEDIA_RAW_VIDEO;
mh->start_time = (bigtime_t) (1000000.0 * fFrame
/ fOutputVideoFormat.field_rate);
mh->u.raw_video.field_sequence = fFrame;
mh->u.raw_video.first_active_line = 1;
mh->u.raw_video.line_count = fOutputVideoFormat.display.line_count;
*outFrameCount = 1;
fFrame++; fFrame++;
mh->start_time = (bigtime_t) (1000000.0 * fFrame / fOutputVideoFormat.field_rate); PRINT(("%p->XvidDecoder::Decode() - start_time=%02d:%02d.%02d "
mh->u.raw_video.field_sequence = fFrame; "field_sequence=%u\n", this,
mh->u.raw_video.line_count = fOutputVideoFormat.display.line_count; int((mh->start_time / 60000000) % 60),
/**/ int((mh->start_time / 1000000) % 60),
PRINT(("XvidDecoder::Decode() - start_time=%02d:%02d.%02d field_sequence=%u\n", int((mh->start_time / 10000) % 100),
int((mh->start_time / 60000000) % 60), mh->u.raw_video.field_sequence));
int((mh->start_time / 1000000) % 60),
int((mh->start_time / 10000) % 100),
mh->u.raw_video.field_sequence));
/**/
#if DEBUG //#if DEBUG
print_media_header(mh); // print_media_header(mh);
print_media_decode_info(info); // print_media_decode_info(info);
#endif //#endif
return B_OK; return B_OK;
} }
@@ -487,16 +563,19 @@ status_t
XvidDecoder::Seek(uint32 inToWhat, int64 inRequiredFrame, int64 *_inOutFrame, XvidDecoder::Seek(uint32 inToWhat, int64 inRequiredFrame, int64 *_inOutFrame,
bigtime_t inRequiredTime, bigtime_t *_inOutTime) bigtime_t inRequiredTime, bigtime_t *_inOutTime)
{ {
PRINT((" XvidDecoder::Seek(flags=%ld, inRequiredFrame=%lld, _inOutFrame=%lld, " PRINT(("%p->XvidDecoder::Seek(flags=%ld, inRequiredFrame=%lld, "
"inRequiredTime=%lld, _inOutTime=%lld)\n", inToWhat, inRequiredFrame, "_inOutFrame=%lld, inRequiredTime=%lld, _inOutTime=%lld)\n",
*_inOutFrame, inRequiredTime, *_inOutTime)); this, inToWhat, inRequiredFrame, *_inOutFrame, inRequiredTime,
*_inOutTime));
// printf(" XvidDecoder::Reset(flags=%ld, inRequiredFrame=%lld, _inOutFrame=%lld, " #if PROPER_SEEKING
// "inRequiredTime=%lld, _inOutTime=%lld)\n", inToWhat, inRequiredFrame, status_t ret = B_OK;
// *_inOutFrame, inRequiredTime, *_inOutTime); if (inToWhat == B_SEEK_BY_FRAME) {
printf("%p->XvidDecoder::Reset(B_SEEK_BY_FRAME, inRequiredFrame=%lld,\n"
" _inOutFrame=%lld, inRequiredTime=%lld, _inOutTime=%lld)\n",
this, inRequiredFrame, *_inOutFrame, inRequiredTime, *_inOutTime);
// status_t ret = B_OK;
// if (inToWhat & B_MEDIA_SEEK_TO_FRAME) {
// int64 wantedFrame = *_inOutFrame; // int64 wantedFrame = *_inOutFrame;
// ret = fTrack->FindKeyFrameForFrame(_inOutFrame, B_MEDIA_SEEK_CLOSEST_BACKWARD); // ret = fTrack->FindKeyFrameForFrame(_inOutFrame, B_MEDIA_SEEK_CLOSEST_BACKWARD);
// if (ret == B_OK && *_inOutFrame != wantedFrame) { // if (ret == B_OK && *_inOutFrame != wantedFrame) {
@@ -504,7 +583,12 @@ XvidDecoder::Seek(uint32 inToWhat, int64 inRequiredFrame, int64 *_inOutFrame,
// // note, this might cause us to enter the function // // note, this might cause us to enter the function
// // again, but that's ok as long as we can seek to the frame // // again, but that's ok as long as we can seek to the frame
// } // }
// } else if (inToWhat & B_MEDIA_SEEK_TO_TIME) { } else if (inToWhat == B_SEEK_BY_TIME) {
printf("%p->XvidDecoder::Reset(B_SEEK_BY_TIME, inRequiredFrame=%lld,\n"
" _inOutFrame=%lld, inRequiredTime=%lld, _inOutTime=%lld)\n",
this, inRequiredFrame, *_inOutFrame, inRequiredTime, *_inOutTime);
// bigtime_t wantedTime = *_inOutTime; // bigtime_t wantedTime = *_inOutTime;
// ret = fTrack->FindKeyFrameForTime(_inOutTime, B_MEDIA_SEEK_CLOSEST_BACKWARD); // ret = fTrack->FindKeyFrameForTime(_inOutTime, B_MEDIA_SEEK_CLOSEST_BACKWARD);
// if (ret == B_OK && *_inOutTime != wantedTime) { // if (ret == B_OK && *_inOutTime != wantedTime) {
@@ -513,14 +597,14 @@ XvidDecoder::Seek(uint32 inToWhat, int64 inRequiredFrame, int64 *_inOutFrame,
// // again, but that's ok as long as we can seek to the frame // // again, but that's ok as long as we can seek to the frame
// *_inOutFrame = fTrack->CurrentFrame(); // *_inOutFrame = fTrack->CurrentFrame();
// } // }
// } }
//
// if (ret != B_OK) { if (ret != B_OK) {
// fprintf(stderr, "XvidDecoder::Seek() - failed to seek\n"); fprintf(stderr, "%p->XvidDecoder::Reset() - failed to seek\n", this);
// return ret; return ret;
// } }
// #endif // PROPER_SEEKING
// TODO: reset xvid decode info?
fFrame = *_inOutFrame; fFrame = *_inOutFrame;
fChunkBuffer = NULL; fChunkBuffer = NULL;
@@ -528,6 +612,7 @@ XvidDecoder::Seek(uint32 inToWhat, int64 inRequiredFrame, int64 *_inOutFrame,
fChunkBufferSize = 0; fChunkBufferSize = 0;
fLeftInChunkBuffer = 0; fLeftInChunkBuffer = 0;
// this will cause the xvid core to discard any cached stuff
fDiscontinuity = true; fDiscontinuity = true;
return B_OK; return B_OK;
@@ -541,11 +626,10 @@ XvidDecoder::Seek(uint32 inToWhat, int64 inRequiredFrame, int64 *_inOutFrame,
int int
XvidDecoder::_XvidInit(int useAssembler, int debugLevel) XvidDecoder::_XvidInit(int useAssembler, int debugLevel)
{ {
int ret = _XvidUninit(); if (fXvidDecoderHandle != NULL)
if (ret < 0) return 0;
return ret;
xvid_gbl_init_t xvidGlobalInit; xvid_gbl_init_t xvidGlobalInit;
xvid_dec_create_t xvidDecoderCreate; xvid_dec_create_t xvidDecoderCreate;
// reset the structure with zeros // reset the structure with zeros
@@ -576,7 +660,7 @@ XvidDecoder::_XvidInit(int useAssembler, int debugLevel)
xvidDecoderCreate.width = 0; xvidDecoderCreate.width = 0;
xvidDecoderCreate.height = 0; xvidDecoderCreate.height = 0;
ret = xvid_decore(NULL, XVID_DEC_CREATE, &xvidDecoderCreate, NULL); int ret = xvid_decore(NULL, XVID_DEC_CREATE, &xvidDecoderCreate, NULL);
if (ret == 0) if (ret == 0)
fXvidDecoderHandle = xvidDecoderCreate.handle; fXvidDecoderHandle = xvidDecoderCreate.handle;
@@ -599,15 +683,28 @@ XvidDecoder::_XvidUninit()
return ret; return ret;
} }
// handle_fp_exeption
static void
handle_fp_exeption(int sig, void* opaque)
{
printf("_XvidDecode(): WARNING: Xvid decoder raised SIGFPE exception.\n");
// TODO: enable when fenv.h is available
// feclearexcept(FE_ALL_EXCEPT);
//jump back before xvid_decore() and take the other branch
siglongjmp((sigjmp_buf)opaque, 1);
}
// _XvidDecode // _XvidDecode
int int
XvidDecoder::_XvidDecode(uchar *istream, uchar *ostream, int inStreamSize, XvidDecoder::_XvidDecode(uchar *inStream, uchar *outStream, int inStreamSize,
xvid_dec_stats_t* xvidDecoderStats, bool hurryUp) xvid_dec_stats_t* xvidDecoderStats, bool hurryUp)
{ {
PRINT(("XvidDecoder::_XvidDecode(%p, %p, %d)\n", istream, ostream, PRINT(("%p->XvidDecoder::_XvidDecode(%p, %p, %d)\n", this, inStream,
inStreamSize)); outStream, inStreamSize));
if (istream == NULL || inStreamSize == 0) if (inStream == NULL || inStreamSize == 0)
return -1; return -1;
xvid_dec_frame_t xvid_dec_frame; xvid_dec_frame_t xvid_dec_frame;
@@ -630,17 +727,43 @@ XvidDecoder::_XvidDecode(uchar *istream, uchar *ostream, int inStreamSize,
} }
// input stream // input stream
xvid_dec_frame.bitstream = istream; xvid_dec_frame.bitstream = inStream;
xvid_dec_frame.length = inStreamSize; xvid_dec_frame.length = inStreamSize;
// output frame structure // output frame structure
xvid_dec_frame.output.plane[0] = ostream; xvid_dec_frame.output.plane[0] = outStream;
xvid_dec_frame.output.stride[0] = ostream ? xvid_dec_frame.output.stride[0] = outStream ?
fOutputVideoFormat.display.bytes_per_row : 0; fOutputVideoFormat.display.bytes_per_row : 0;
xvid_dec_frame.output.csp = fXvidColorspace; xvid_dec_frame.output.csp = fXvidColorspace;
return xvid_decore(fXvidDecoderHandle, XVID_DEC_DECODE, &xvid_dec_frame, // prepare for possible floating point exception
xvidDecoderStats); sigjmp_buf preDecoreEnv;
struct sigaction action;
struct sigaction oldAction;
memset(&action, 0, sizeof(struct sigaction));
action.sa_flags = 0;
action.sa_handler = (__signal_func_ptr)handle_fp_exeption;
action.sa_userdata = preDecoreEnv;
if (sigaction(SIGFPE, &action, &oldAction) != 0)
return -1;
int usedBytes;
if (sigsetjmp(preDecoreEnv, 1) == 0) {
// decode
usedBytes = xvid_decore(fXvidDecoderHandle, XVID_DEC_DECODE,
&xvid_dec_frame, xvidDecoderStats);
} else {
// make sure the state changes before calling xvid_decore again
// or we'll cause the same exception
usedBytes = 1;
}
if (sigaction(SIGFPE, &oldAction, &action) != 0)
return -1;
return usedBytes;
} }
// #pragma mark - // #pragma mark -
@@ -690,7 +813,7 @@ XvidPlugin::GetSupportedFormats(media_format** _mediaFormatArray, size_t *_count
if (err < B_OK) { if (err < B_OK) {
fprintf(stderr, "XvidDecoder: BMediaFormats::MakeFormatFor: " fprintf(stderr, "XvidDecoder: BMediaFormats::MakeFormatFor: "
"error %s\n", strerror(err)); "error %s\n", strerror(err));
return err; continue;
} }
gXvidFormats[i] = format; gXvidFormats[i] = format;
@@ -50,10 +50,6 @@ class XvidDecoder : public Decoder {
bigtime_t inRequiredTime, bigtime_t inRequiredTime,
bigtime_t* _inOutTime); bigtime_t* _inOutTime);
protected:
media_header fHeader;
media_decode_info fInfo;
private: private:
int _XvidInit(int useAssembler, int debugLevel); int _XvidInit(int useAssembler, int debugLevel);
int _XvidUninit(); int _XvidUninit();
@@ -73,6 +69,7 @@ class XvidDecoder : public Decoder {
int32 fIndexInCodecTable; int32 fIndexInCodecTable;
const void* fChunkBuffer; const void* fChunkBuffer;
uint8* fWrappedChunkBuffer;
const char* fChunkBufferHandle; const char* fChunkBufferHandle;
size_t fChunkBufferSize; size_t fChunkBufferSize;
int32 fLeftInChunkBuffer; int32 fLeftInChunkBuffer;