* 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:
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user