* implemented an xvid based decoder plugin

-> It is currently disabled, because it won't link.
   I would need to add xvid to the tree, but that would add nasm
   as a build dependency. I need to talk this over with Ingo. However,
   it is quite easy to build xvid yourself and link the decoder, should
   you want to test it. It works fine under ZETA when compiled to use
   the undocumented R5 Decoder API.



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21504 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2007-06-25 21:11:55 +00:00
parent ac9d119566
commit 880e4292a1
6 changed files with 1725 additions and 0 deletions

View File

@ -0,0 +1,16 @@
SubDir HAIKU_TOP src add-ons media plugins xvid_decoder ;
UsePrivateHeaders media ;
#SubDirHdrs [ FDirName $(SUBDIR) libxvid ] ;
Addon xvid.decoder :
XvidDecoder.cpp
supported_codecs.cpp
:
libxvid.a
be
libmedia.so
;
#SubInclude HAIKU_TOP src add-ons media plugins xvid_decoder libxvid ;

View File

@ -0,0 +1,718 @@
/*
* XvidDecoder.cpp - XviD plugin for the Haiku Operating System
*
* Copyright (C) 2007 Stephan Aßmus <superstippi@gmx.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#define DEBUG 0
#include "XvidDecoder.h"
#include <new>
#include <string.h>
#include <ByteOrder.h>
#include <Debug.h>
#include <MediaTrack.h>
#include <OS.h>
#include <MediaDefs.h>
#include <File.h>
#include <Bitmap.h>
#include "supported_codecs.h"
using std::nothrow;
#if DEBUG
static const char*
media_type_name(int type)
{
switch (type) {
case B_MEDIA_NO_TYPE:
return "B_MEDIA_NO_TYPE";
case B_MEDIA_RAW_AUDIO:
return "B_MEDIA_RAW_AUDIO";
case B_MEDIA_RAW_VIDEO:
return "B_MEDIA_RAW_VIDEO";
case B_MEDIA_VBL:
return "B_MEDIA_VBL";
case B_MEDIA_TIMECODE:
return "B_MEDIA_TIMECODE";
case B_MEDIA_MIDI:
return "B_MEDIA_MIDI";
case B_MEDIA_TEXT:
return "B_MEDIA_TEXT";
case B_MEDIA_HTML:
return "B_MEDIA_HTML";
case B_MEDIA_MULTISTREAM:
return "B_MEDIA_MULTISTREAM";
case B_MEDIA_PARAMETERS:
return "B_MEDIA_PARAMETERS";
case B_MEDIA_ENCODED_AUDIO:
return "B_MEDIA_ENCODED_AUDIO";
case B_MEDIA_ENCODED_VIDEO:
return "B_MEDIA_ENCODED_VIDEO";
case B_MEDIA_UNKNOWN_TYPE:
default:
return "B_MEDIA_UNKNOWN_TYPE";
}
}
static char
make_printable_char(uchar c)
{
if (c >= 0x20 && c < 0x7F)
return c;
return '.';
}
static void
print_hex(unsigned char* buff, int len)
{
int i, j;
for(i=0; i<len+7;i+=8) {
for (j=0; j<8; j++) {
if (i+j < len)
printf("%02X", buff[i+j]);
else
printf(" ");
if (j==3)
printf(" ");
}
printf("\t");
for (j=0; j<8; j++) {
if (i+j < len)
printf("%c", make_printable_char(buff[i+j]));
else
printf(" ");
}
printf("\n");
}
}
static void
print_media_header(media_header* mh)
{
printf("media_header {%s, size_used: %ld, start_time: %lld (%02d:%02d.%02d), "
"field_sequence=%lu, user_data_type: .4s, file_pos: %ld, orig_size: %ld, "
"data_offset: %ld}\n",
media_type_name(mh->type), mh->size_used, mh->start_time,
int((mh->start_time / 60000000) % 60),
int((mh->start_time / 1000000) % 60),
int((mh->start_time / 10000) % 100),
(long)mh->u.raw_video.field_sequence,
//&(mh->user_data_type),
(long)mh->file_pos,
(long)mh->orig_size,
mh->data_offset);
}
static void
print_media_decode_info(media_decode_info *info)
{
if (info) {
printf("media_decode_info {time_to_decode: %lld, "
"file_format_data_size: %ld, codec_data_size: %ld}\n",
info->time_to_decode, info->file_format_data_size,
info->codec_data_size);
} else
printf("media_decode_info (null)\n");
}
#endif // DEBUG
// #pragma mark -
#define MIN_USEFUL_BYTES 1
XvidDecoder::XvidDecoder()
: Decoder()
, fInputFormat()
, fOutputVideoFormat()
, fXvidDecoderHandle(NULL)
, fXvidColorspace(0)
, fFrame(0)
, fIndexInCodecTable(-1)
, fChunkBuffer(NULL)
, fChunkBufferHandle(NULL)
, fChunkBufferSize(0)
, fLeftInChunkBuffer(0)
, fDiscontinuity(false)
{
}
XvidDecoder::~XvidDecoder()
{
_XvidUninit();
}
void
XvidDecoder::GetCodecInfo(media_codec_info* mci)
{
PRINT(("XvidDecoder::GetCodecInfo()\n"));
if (mci == NULL)
return;// B_BAD_VALUE;
if (fIndexInCodecTable < 0)
return;// B_NO_INIT;
sprintf(mci->short_name, "xvid");
sprintf(mci->pretty_name, "xvid - %s)",
gCodecTable[fIndexInCodecTable].prettyName);
mci->id = 0;
mci->sub_id = 0;
return;// B_OK;
}
status_t
XvidDecoder::Setup(media_format* inputFormat, const void* inInfo,
size_t inSize)
{
if (inputFormat == NULL)
return B_BAD_VALUE;
if (inputFormat->type != B_MEDIA_ENCODED_VIDEO)
return B_BAD_VALUE;
PRINT(("XvidDecoder::Sniff()\n"));
//#if DEBUG
// char buffer[1024];
// string_for_format(*inputFormat, buffer, sizeof(buffer));
// PRINT((" inputFormat=%s\n", buffer));
// PRINT((" inSize=%d\n", inSize));
// print_hex((uchar*)inInfo, inSize);
// PRINT((" user_data_type=%08lx\n", (int)inputFormat->user_data_type));
// print_hex((uchar*)inputFormat->user_data, 48);
//#endif
uint32 codecID = 0;
media_format_family familyID = B_ANY_FORMAT_FAMILY;
// hacky... get the exact 4CC from there if it's in, to help xvid
// handle broken files
// if ((inputFormat->user_data_type == B_CODEC_TYPE_INFO)
// && !memcmp(inputFormat->user_data, "AVI ", 4)) {
// codecID = ((uint32*)inputFormat->user_data)[1];
// familyID = B_AVI_FORMAT_FAMILY;
// PRINT(("XvidDecoder::Sniff() - AVI 4CC: %4s\n",
// inputFormat->user_data + 4));
// }
if (codecID == 0) {
BMediaFormats formats;
media_format_description descr;
if (formats.GetCodeFor(*inputFormat, B_QUICKTIME_FORMAT_FAMILY,
&descr) == B_OK) {
codecID = descr.u.quicktime.codec;
familyID = B_QUICKTIME_FORMAT_FAMILY;
#if DEBUG
uint32 bigEndianID = B_HOST_TO_BENDIAN_INT32(codecID);
PRINT(("XvidDecoder::Sniff() - QT 4CC: %.4s\n", (const char*)&bigEndianID));
#endif
} else if (formats.GetCodeFor(*inputFormat, B_AVI_FORMAT_FAMILY,
&descr) == B_OK) {
codecID = descr.u.avi.codec;
familyID = B_AVI_FORMAT_FAMILY;
#if DEBUG
uint32 bigEndianID = B_HOST_TO_BENDIAN_INT32(codecID);
PRINT(("XvidDecoder::Sniff() - AVI 4CC: %.4s\n", (const char*)&codecID));
#endif
}
}
if (codecID == 0)
return B_ERROR;
for (int32 i = 0; i < gSupportedCodecsCount; i++) {
if (gCodecTable[i].family == familyID
&& gCodecTable[i].fourcc == codecID) {
PRINT(("XvidDecoder::Sniff() - found codec in the table at %ld.\n", i));
fIndexInCodecTable = i;
fInputFormat = *inputFormat;
return B_OK;
}
}
PRINT(("XvidDecoder::Sniff() - no matching codec found in the table.\n"));
return B_ERROR;
}
status_t
XvidDecoder::NegotiateOutputFormat(media_format* _inoutFormat)
{
PRINT((" XvidDecoder::NegotiateOutputFormat()\n"));
if (_inoutFormat == NULL)
return B_BAD_VALUE;
#if DEBUG
char buffer[1024];
if (string_for_format(*_inoutFormat, buffer, sizeof(buffer)) == B_OK)
PRINT((" _inoutFormat = %s\n", buffer));
#endif
// init our own output format from the sniffed values
fOutputVideoFormat = fInputFormat.u.encoded_video.output;
// suggest a default colorspace
color_space askedFormat = _inoutFormat->u.raw_video.display.format;
color_space supportedFormat;
uint32 bpr;
switch (askedFormat) {
case B_NO_COLOR_SPACE:
// suggest preferred format
case B_YCbCr422:
supportedFormat = B_YCbCr422;
fXvidColorspace = XVID_CSP_YUY2;
bpr = fOutputVideoFormat.display.line_width * 2;
break;
case B_YCbCr420:
supportedFormat = askedFormat;
fXvidColorspace = XVID_CSP_I420;
bpr = fOutputVideoFormat.display.line_width
+ (fOutputVideoFormat.display.line_width + 1) / 2;
break;
case B_RGB32_BIG:
supportedFormat = askedFormat;
fXvidColorspace = XVID_CSP_RGBA;
bpr = fOutputVideoFormat.display.line_width * 4;
break;
case B_RGB24:
supportedFormat = askedFormat;
fXvidColorspace = XVID_CSP_BGR;
bpr = fOutputVideoFormat.display.line_width * 3;
break;
case B_RGB16:
supportedFormat = askedFormat;
fXvidColorspace = XVID_CSP_RGB565;
bpr = fOutputVideoFormat.display.line_width * 2;
break;
case B_RGB15:
supportedFormat = askedFormat;
fXvidColorspace = XVID_CSP_RGB555;
bpr = fOutputVideoFormat.display.line_width * 2;
break;
default:
fprintf(stderr, "XvidDecoder::NegotiateOutputFormat() - Application "
"asked for unsupported colorspace, using fallback "
"of B_RGB32.\n");
case B_RGB32:
supportedFormat = B_RGB32;
fXvidColorspace = XVID_CSP_BGRA;
bpr = fOutputVideoFormat.display.line_width * 4;
break;
}
// enforce the colorspace we support
fOutputVideoFormat.display.format = supportedFormat;
_inoutFormat->u.raw_video.display.format = supportedFormat;
// enforce supported bytes per row
bpr = max_c(_inoutFormat->u.raw_video.display.bytes_per_row,
((bpr + 3) / 4) * 4);
fOutputVideoFormat.display.bytes_per_row = bpr;
_inoutFormat->u.raw_video.display.bytes_per_row = bpr;
_inoutFormat->type = B_MEDIA_RAW_VIDEO;
_inoutFormat->u.raw_video = fOutputVideoFormat;
_inoutFormat->require_flags = 0;
_inoutFormat->deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS;
#if DEBUG
string_for_format(*_inoutFormat, buffer, sizeof(buffer));
PRINT(("XvidDecoder: out_format=%s\n", buffer));
#endif
return _XvidInit(true, 0) == 0 ? B_OK : B_ERROR;
}
status_t
XvidDecoder::Decode(void* outBuffer, int64 *outFrameCount, media_header *mh,
media_decode_info *info)
{
if (outBuffer == NULL || outFrameCount == NULL || mh == NULL)
return B_BAD_VALUE;
PRINT(("XvidDecoder::Decode()\n"));
// are we in a hurry ?
bool hurryUp = (!info || (info->time_to_decode > 0)) ? false : true;
mh->type = B_MEDIA_RAW_VIDEO;
mh->start_time = 0;
mh->size_used = 0;
mh->file_pos = 0;
mh->orig_size = 0;
mh->data_offset = 0;
mh->u.raw_video.field_gamma = 1.0;
mh->u.raw_video.field_sequence = 0;
mh->u.raw_video.field_number = 0;
mh->u.raw_video.pulldown_number = 0;
mh->u.raw_video.first_active_line = 1;
mh->u.raw_video.line_count = 0;
#if DEBUG
int32 chunk = 0;
#endif
status_t ret = B_OK;
do {
if (fLeftInChunkBuffer <= MIN_USEFUL_BYTES) {
// read new data
ret = GetNextChunk(&fChunkBuffer, &fChunkBufferSize, mh);
if (ret >= B_OK) {
fLeftInChunkBuffer = fChunkBufferSize;
fChunkBufferHandle = (const char*)fChunkBuffer;
} else {
fChunkBufferSize = 0;
fChunkBuffer = NULL;
fChunkBufferHandle = NULL;
}
}
// Check if there is a negative number of useful bytes left in buffer
// This means we went too far
if (!fChunkBufferHandle || fLeftInChunkBuffer < 0) {
break;
}
xvid_dec_stats_t xvidDecoderStats;
// This loop is needed to handle VOL/NVOP reading
do {
// Decode frame
int usedBytes = _XvidDecode((uchar*)fChunkBufferHandle, (uchar*)outBuffer,
fLeftInChunkBuffer, &xvidDecoderStats, hurryUp);
// Resize image buffer if needed
if (xvidDecoderStats.type == XVID_TYPE_VOL) {
// Check if old buffer is smaller
if ((int)(fOutputVideoFormat.display.line_width
* fOutputVideoFormat.display.line_count)
< xvidDecoderStats.data.vol.width
* xvidDecoderStats.data.vol.height) {
PRINT(("XvidDecoder::Decode() - image size changed!\n",
xvidDecoderStats.data.vol.width,
xvidDecoderStats.data.vol.height));
return B_ERROR;
}
}
// Update buffer pointers
if (usedBytes > 0) {
fChunkBufferHandle += usedBytes;
fLeftInChunkBuffer -= usedBytes;
}
PRINT(("XvidDecoder::Decode() - chunk %d: %d bytes consumed, "
"%d bytes in buffer\n", chunk++, usedBytes, fLeftInChunkBuffer));
} while (xvidDecoderStats.type <= 0
&& fLeftInChunkBuffer > MIN_USEFUL_BYTES);
if (xvidDecoderStats.type > XVID_TYPE_NOTHING) {
// got a full frame
mh->size_used = fOutputVideoFormat.display.line_count
* fOutputVideoFormat.display.bytes_per_row;
break;
}
} while (fLeftInChunkBuffer > MIN_USEFUL_BYTES || ret >= B_OK);
if (ret != B_OK)
return ret;
fFrame++;
mh->start_time = (bigtime_t) (1000000.0 * fFrame / fOutputVideoFormat.field_rate);
mh->u.raw_video.field_sequence = fFrame;
mh->u.raw_video.line_count = fOutputVideoFormat.display.line_count;
/**/
PRINT(("XvidDecoder::Decode() - start_time=%02d:%02d.%02d field_sequence=%u\n",
int((mh->start_time / 60000000) % 60),
int((mh->start_time / 1000000) % 60),
int((mh->start_time / 10000) % 100),
mh->u.raw_video.field_sequence));
/**/
#if DEBUG
print_media_header(mh);
print_media_decode_info(info);
#endif
return B_OK;
}
status_t
XvidDecoder::Seek(uint32 inToWhat, int64 inRequiredFrame, int64 *_inOutFrame,
bigtime_t inRequiredTime, bigtime_t *_inOutTime)
{
PRINT((" XvidDecoder::Seek(flags=%ld, inRequiredFrame=%lld, _inOutFrame=%lld, "
"inRequiredTime=%lld, _inOutTime=%lld)\n", inToWhat, inRequiredFrame,
*_inOutFrame, inRequiredTime, *_inOutTime));
// printf(" XvidDecoder::Reset(flags=%ld, inRequiredFrame=%lld, _inOutFrame=%lld, "
// "inRequiredTime=%lld, _inOutTime=%lld)\n", inToWhat, inRequiredFrame,
// *_inOutFrame, inRequiredTime, *_inOutTime);
// status_t ret = B_OK;
// if (inToWhat & B_MEDIA_SEEK_TO_FRAME) {
// int64 wantedFrame = *_inOutFrame;
// ret = fTrack->FindKeyFrameForFrame(_inOutFrame, B_MEDIA_SEEK_CLOSEST_BACKWARD);
// if (ret == B_OK && *_inOutFrame != wantedFrame) {
// ret = fTrack->SeekToFrame(_inOutFrame, 0);
// // note, this might cause us to enter the function
// // again, but that's ok as long as we can seek to the frame
// }
// } else if (inToWhat & B_MEDIA_SEEK_TO_TIME) {
// bigtime_t wantedTime = *_inOutTime;
// ret = fTrack->FindKeyFrameForTime(_inOutTime, B_MEDIA_SEEK_CLOSEST_BACKWARD);
// if (ret == B_OK && *_inOutTime != wantedTime) {
// ret = fTrack->SeekToTime(_inOutTime, 0);
// // note, this might cause us to enter the function
// // again, but that's ok as long as we can seek to the frame
// *_inOutFrame = fTrack->CurrentFrame();
// }
// }
//
// if (ret != B_OK) {
// fprintf(stderr, "XvidDecoder::Seek() - failed to seek\n");
// return ret;
// }
//
// TODO: reset xvid decode info?
fFrame = *_inOutFrame;
fChunkBuffer = NULL;
fChunkBufferHandle = NULL;
fChunkBufferSize = 0;
fLeftInChunkBuffer = 0;
fDiscontinuity = true;
return B_OK;
}
// #pragma mark -
// _XvidInit
int
XvidDecoder::_XvidInit(int useAssembler, int debugLevel)
{
int ret = _XvidUninit();
if (ret < 0)
return ret;
xvid_gbl_init_t xvidGlobalInit;
xvid_dec_create_t xvidDecoderCreate;
// reset the structure with zeros
memset(&xvidGlobalInit, 0, sizeof(xvid_gbl_init_t));
memset(&xvidDecoderCreate, 0, sizeof(xvid_dec_create_t));
// XviD core initialization
// version
xvidGlobalInit.version = XVID_VERSION;
// assembly usage setting
if (useAssembler)
xvidGlobalInit.cpu_flags = 0;
else
xvidGlobalInit.cpu_flags = XVID_CPU_FORCE;
xvidGlobalInit.debug = debugLevel;
xvid_global(NULL, 0, &xvidGlobalInit, NULL);
// XviD encoder initialization
// version
xvidDecoderCreate.version = XVID_VERSION;
// bitmap dimensions -- xvidcore will resize when needed
xvidDecoderCreate.width = 0;
xvidDecoderCreate.height = 0;
ret = xvid_decore(NULL, XVID_DEC_CREATE, &xvidDecoderCreate, NULL);
if (ret == 0)
fXvidDecoderHandle = xvidDecoderCreate.handle;
return ret;
}
// _XvidUninit
int
XvidDecoder::_XvidUninit()
{
if (fXvidDecoderHandle == NULL)
return 0;
int ret = xvid_decore(fXvidDecoderHandle, XVID_DEC_DESTROY, NULL, NULL);
if (ret == 0) {
fXvidDecoderHandle = NULL;
fXvidColorspace = 0;
}
return ret;
}
// _XvidDecode
int
XvidDecoder::_XvidDecode(uchar *istream, uchar *ostream, int inStreamSize,
xvid_dec_stats_t* xvidDecoderStats, bool hurryUp)
{
PRINT(("XvidDecoder::_XvidDecode(%p, %p, %d)\n", istream, ostream,
inStreamSize));
if (istream == NULL || inStreamSize == 0)
return -1;
xvid_dec_frame_t xvid_dec_frame;
// reset all structures
memset(&xvid_dec_frame, 0, sizeof(xvid_dec_frame_t));
memset(xvidDecoderStats, 0, sizeof(xvid_dec_stats_t));
// set version
xvid_dec_frame.version = XVID_VERSION;
xvidDecoderStats->version = XVID_VERSION;
// no general flags to set
xvid_dec_frame.general = 0; //XVID_DEBLOCKY | XVID_DEBLOCKUV;
if (hurryUp)
xvid_dec_frame.general |= XVID_LOWDELAY;
if (fDiscontinuity) {
xvid_dec_frame.general |= XVID_DISCONTINUITY;
fDiscontinuity = false;
}
// input stream
xvid_dec_frame.bitstream = istream;
xvid_dec_frame.length = inStreamSize;
// output frame structure
xvid_dec_frame.output.plane[0] = ostream;
xvid_dec_frame.output.stride[0] = ostream ?
fOutputVideoFormat.display.bytes_per_row : 0;
xvid_dec_frame.output.csp = fXvidColorspace;
return xvid_decore(fXvidDecoderHandle, XVID_DEC_DECODE, &xvid_dec_frame,
xvidDecoderStats);
}
// #pragma mark -
status_t
XvidPlugin::GetSupportedFormats(media_format** _mediaFormatArray, size_t *_count)
{
PRINT(("XvidDecoder::register_decoder()\n"));
static bool codecsRegistered = false;
if (codecsRegistered)
return B_OK;
codecsRegistered = true;
PRINT(("XvidDecoder: registering %d codecs\n", gSupportedCodecsCount));
media_format_description descr[gSupportedCodecsCount];
for (int i = 0; i < gSupportedCodecsCount; i++) {
descr[i].family = gCodecTable[i].family;
switch(descr[i].family) {
case B_AVI_FORMAT_FAMILY:
descr[i].u.avi.codec = gCodecTable[i].fourcc;
break;
case B_MPEG_FORMAT_FAMILY:
descr[i].u.mpeg.id = gCodecTable[i].fourcc;
break;
case B_QUICKTIME_FORMAT_FAMILY:
descr[i].u.quicktime.codec = gCodecTable[i].fourcc;
break;
default:
break;
}
}
BMediaFormats formats;
for (int i = 0; i < gSupportedCodecsCount; i++) {
media_format format;
format.type = B_MEDIA_ENCODED_VIDEO;
format.u.encoded_video = media_encoded_video_format::wildcard;
format.require_flags = 0;
format.deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS;
status_t err = formats.MakeFormatFor(&descr[i], 1, &format);
if (err < B_OK) {
fprintf(stderr, "XvidDecoder: BMediaFormats::MakeFormatFor: "
"error %s\n", strerror(err));
return err;
}
gXvidFormats[i] = format;
}
*_mediaFormatArray = gXvidFormats;
*_count = gSupportedCodecsCount;
return B_OK;
}
Decoder*
XvidPlugin::NewDecoder(uint index)
{
return new (nothrow) XvidDecoder();
}
MediaPlugin *instantiate_plugin()
{
return new (nothrow) XvidPlugin;
}

View File

@ -0,0 +1,92 @@
/*
* XvidDecoder.h - XviD plugin for the Haiku Operating System
*
* Copyright (C) 2007 Stephan Aßmus <superstippi@gmx.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef XVID_DECODER_H
#define XVID_DECODER_H
#include <DataIO.h>
#include <MediaFormats.h>
#include "DecoderPlugin.h"
#include "xvid.h"
class XvidDecoder : public Decoder {
public:
XvidDecoder();
virtual ~XvidDecoder();
virtual void GetCodecInfo(media_codec_info *mci);
virtual status_t Setup(media_format* inputFormat,
const void* inInfo, size_t inSize);
virtual status_t NegotiateOutputFormat(
media_format *outputFormat);
virtual status_t Decode(void* outBuffer, int64* outFrameCount,
media_header* mh, media_decode_info* info);
virtual status_t Seek(uint32 inToWhat, int64 inRequiredFrame,
int64* _inOutFrame,
bigtime_t inRequiredTime,
bigtime_t* _inOutTime);
protected:
media_header fHeader;
media_decode_info fInfo;
private:
int _XvidInit(int useAssembler, int debugLevel);
int _XvidUninit();
int _XvidDecode(uchar *istream, uchar *ostream,
int inStreamSize,
xvid_dec_stats_t* xvidDecoderStats,
bool hurryUp);
media_format fInputFormat;
media_raw_video_format fOutputVideoFormat;
void* fXvidDecoderHandle;
int fXvidColorspace;
int64 fFrame;
int32 fIndexInCodecTable;
const void* fChunkBuffer;
const char* fChunkBufferHandle;
size_t fChunkBufferSize;
int32 fLeftInChunkBuffer;
bool fDiscontinuity;
};
class XvidPlugin : public DecoderPlugin {
public:
Decoder* NewDecoder(uint index);
status_t GetSupportedFormats(
media_format** formats, size_t* count);
};
#endif // XVID_DECODER_H

View File

@ -0,0 +1,75 @@
/*
* supported_codecs.cpp - XviD plugin for the Haiku Operating System
*
* Copyright (C) 2007 Stephan Aßmus <superstippi@gmx.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include <MediaDefs.h>
#include "supported_codecs.h"
const struct codec_table_entry gCodecTable[] = {
{B_QUICKTIME_FORMAT_FAMILY, '3IV1', "3ivx Delta v1"},
{B_QUICKTIME_FORMAT_FAMILY, '3IV2', "3ivx v2"},
{B_QUICKTIME_FORMAT_FAMILY, 'DIVX', "MPEG4 Video"}, // OpenDivX
{B_QUICKTIME_FORMAT_FAMILY, 'divx', "MPEG4 Video"}, // OpenDivX
{B_QUICKTIME_FORMAT_FAMILY, 'mp4v', "MPEG4 Video"}, // OpenDivX
{B_QUICKTIME_FORMAT_FAMILY, 'XVID', "XVID"}, // OpenDivX
{B_AVI_FORMAT_FAMILY, 'DIVX', "MPEG4 Video"}, // OpenDivX
{B_AVI_FORMAT_FAMILY, 'divx', "MPEG4 Video"}, // OpenDivX
{B_AVI_FORMAT_FAMILY, 'XVID', "XVID"}, // XVID
{B_AVI_FORMAT_FAMILY, 'xvid', "XVID"}, // XVID
{B_AVI_FORMAT_FAMILY, 'DX50', "DivX 5"}, // DivX 5.0
{B_AVI_FORMAT_FAMILY, 'dx50', "DivX 5"}, // DivX 5.0
{B_AVI_FORMAT_FAMILY, 'MP4S', "MPEG4 Video"}, // from ffmpeg
{B_AVI_FORMAT_FAMILY, 'M2S2', "MPEG4 Video"}, // from ffmpeg
{B_AVI_FORMAT_FAMILY, 'M4S2', "MPEG4 Video"}, // from ffmpeg
{B_AVI_FORMAT_FAMILY, 'DIV1', "MPEG4 Video"}, // from mplayer
{B_AVI_FORMAT_FAMILY, 'BLZ0', "MPEG4 Video"}, // from mplayer
{B_AVI_FORMAT_FAMILY, 'mp4v', "MPEG4 Video"}, // from mplayer -- OpenDivx
{B_AVI_FORMAT_FAMILY, 'UMP4', "MPEG4 Video"}, // from mplayer
{B_AVI_FORMAT_FAMILY, 'FMP4', "FFMpeg MPEG4 Video"}, // ffmpeg's own version
{B_AVI_FORMAT_FAMILY, '\004\0\0\0', "MPEG4 Video"}, // some broken avi use this
// {B_AVI_FORMAT_FAMILY, 'DIV3', "DivX ;-)"}, // default signature when
// using MSMPEG4
// {B_AVI_FORMAT_FAMILY, 'div3', "DivX ;-)"},
// {B_AVI_FORMAT_FAMILY, 'DIV4', "DivX ;-)"},
// {B_AVI_FORMAT_FAMILY, 'div4', "DivX ;-)"},
// {B_AVI_FORMAT_FAMILY, 'DIV2', "DivX ;-)"},
// {B_AVI_FORMAT_FAMILY, 'DIV5', "DivX ;-)"},
// {B_AVI_FORMAT_FAMILY, 'DIV6', "DivX ;-)"},
// {B_AVI_FORMAT_FAMILY, 'COL0', "DivX ;-)"},
// {B_AVI_FORMAT_FAMILY, 'COL1', "DivX ;-)"},
// {B_AVI_FORMAT_FAMILY, 'MP41', "Microsoft MPEG4 v1"}, // microsoft mpeg4 v1
// {B_AVI_FORMAT_FAMILY, 'MP42', "Microsoft MPEG4 v2"}, // seems to be broken
// {B_AVI_FORMAT_FAMILY, 'MP43', "Microsoft MPEG4 v3"}, // microsoft mpeg4 v3
// {B_AVI_FORMAT_FAMILY, 'MPG3', "Microsoft MPEG4"},
// {B_AVI_FORMAT_FAMILY, 'MPG4', "Microsoft MPEG4"},
// {B_AVI_FORMAT_FAMILY, 'AP41', "Angel Potion MPEG4"}, // AngelPotion 1
};
const int gSupportedCodecsCount = sizeof(gCodecTable) / sizeof(codec_table_entry);
media_format gXvidFormats[gSupportedCodecsCount];

View File

@ -0,0 +1,38 @@
/*
* supported_codecs.h - XviD plugin for the Haiku Operating System
*
* Copyright (C) 2007 Stephan Aßmus <superstippi@gmx.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef SUPPORTED_CODECS_H
#define SUPPORTED_CODECS_H
#include <MediaDefs.h>
struct codec_table_entry {
media_format_family family;
uint32 fourcc;
const char* prettyName;
};
extern const struct codec_table_entry gCodecTable[];
extern const int gSupportedCodecsCount;
extern media_format gXvidFormats[];
#endif // SUPPORTED_CODECS_H

View File

@ -0,0 +1,786 @@
/*****************************************************************************
*
* XVID MPEG-4 VIDEO CODEC
* - XviD Main header file -
*
* Copyright(C) 2001-2004 Peter Ross <pross@xvid.org>
*
* This program is free software ; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: xvid.h,v 1.51.2.4 2006/11/01 10:17:27 Isibaar Exp $
*
****************************************************************************/
#ifndef _XVID_H_
#define _XVID_H_
#ifdef __cplusplus
extern "C" {
#endif
/*****************************************************************************
* versioning
****************************************************************************/
/* versioning
version takes the form "$major.$minor.$patch"
$patch is incremented when there is no api change
$minor is incremented when the api is changed, but remains backwards compatible
$major is incremented when the api is changed significantly
when initialising an xvid structure, you must always zero it, and set the version field.
memset(&struct,0,sizeof(struct));
struct.version = XVID_VERSION;
XVID_UNSTABLE is defined only during development.
*/
#define XVID_MAKE_VERSION(a,b,c) ((((a)&0xff)<<16) | (((b)&0xff)<<8) | ((c)&0xff))
#define XVID_VERSION_MAJOR(a) ((char)(((a)>>16) & 0xff))
#define XVID_VERSION_MINOR(a) ((char)(((a)>> 8) & 0xff))
#define XVID_VERSION_PATCH(a) ((char)(((a)>> 0) & 0xff))
#define XVID_MAKE_API(a,b) ((((a)&0xff)<<16) | (((b)&0xff)<<0))
#define XVID_API_MAJOR(a) (((a)>>16) & 0xff)
#define XVID_API_MINOR(a) (((a)>> 0) & 0xff)
#define XVID_VERSION XVID_MAKE_VERSION(1,1,2)
#define XVID_API XVID_MAKE_API(4, 1)
/* Bitstream Version
* this will be writen into the bitstream to allow easy detection of xvid
* encoder bugs in the decoder, without this it might not possible to
* automatically distinquish between a file which has been encoded with an
* old & buggy XVID from a file which has been encoded with a bugfree version
* see the infamous interlacing bug ...
*
* this MUST be increased if an encoder bug is fixed, increasing it too often
* doesnt hurt but not increasing it could cause difficulty for decoders in the
* future
*/
#define XVID_BS_VERSION 46
/*****************************************************************************
* error codes
****************************************************************************/
/* all functions return values <0 indicate error */
#define XVID_ERR_FAIL -1 /* general fault */
#define XVID_ERR_MEMORY -2 /* memory allocation error */
#define XVID_ERR_FORMAT -3 /* file format error */
#define XVID_ERR_VERSION -4 /* structure version not supported */
#define XVID_ERR_END -5 /* encoder only; end of stream reached */
/*****************************************************************************
* xvid_image_t
****************************************************************************/
/* colorspace values */
#define XVID_CSP_PLANAR (1<< 0) /* 4:2:0 planar (==I420, except for pointers/strides) */
#define XVID_CSP_USER XVID_CSP_PLANAR
#define XVID_CSP_I420 (1<< 1) /* 4:2:0 planar */
#define XVID_CSP_YV12 (1<< 2) /* 4:2:0 planar */
#define XVID_CSP_YUY2 (1<< 3) /* 4:2:2 packed */
#define XVID_CSP_UYVY (1<< 4) /* 4:2:2 packed */
#define XVID_CSP_YVYU (1<< 5) /* 4:2:2 packed */
#define XVID_CSP_BGRA (1<< 6) /* 32-bit bgra packed */
#define XVID_CSP_ABGR (1<< 7) /* 32-bit abgr packed */
#define XVID_CSP_RGBA (1<< 8) /* 32-bit rgba packed */
#define XVID_CSP_ARGB (1<<15) /* 32-bit argb packed */
#define XVID_CSP_BGR (1<< 9) /* 24-bit bgr packed */
#define XVID_CSP_RGB555 (1<<10) /* 16-bit rgb555 packed */
#define XVID_CSP_RGB565 (1<<11) /* 16-bit rgb565 packed */
#define XVID_CSP_SLICE (1<<12) /* decoder only: 4:2:0 planar, per slice rendering */
#define XVID_CSP_INTERNAL (1<<13) /* decoder only: 4:2:0 planar, returns ptrs to internal buffers */
#define XVID_CSP_NULL (1<<14) /* decoder only: dont output anything */
#define XVID_CSP_VFLIP (1<<31) /* vertical flip mask */
/* xvid_image_t
for non-planar colorspaces use only plane[0] and stride[0]
four plane reserved for alpha*/
typedef struct {
int csp; /* [in] colorspace; or with XVID_CSP_VFLIP to perform vertical flip */
void * plane[4]; /* [in] image plane ptrs */
int stride[4]; /* [in] image stride; "bytes per row"*/
} xvid_image_t;
/* video-object-sequence profiles */
#define XVID_PROFILE_S_L0 0x08 /* simple */
#define XVID_PROFILE_S_L1 0x01
#define XVID_PROFILE_S_L2 0x02
#define XVID_PROFILE_S_L3 0x03
#define XVID_PROFILE_ARTS_L1 0x91 /* advanced realtime simple */
#define XVID_PROFILE_ARTS_L2 0x92
#define XVID_PROFILE_ARTS_L3 0x93
#define XVID_PROFILE_ARTS_L4 0x94
#define XVID_PROFILE_AS_L0 0xf0 /* advanced simple */
#define XVID_PROFILE_AS_L1 0xf1
#define XVID_PROFILE_AS_L2 0xf2
#define XVID_PROFILE_AS_L3 0xf3
#define XVID_PROFILE_AS_L4 0xf4
/* aspect ratios */
#define XVID_PAR_11_VGA 1 /* 1:1 vga (square), default if supplied PAR is not a valid value */
#define XVID_PAR_43_PAL 2 /* 4:3 pal (12:11 625-line) */
#define XVID_PAR_43_NTSC 3 /* 4:3 ntsc (10:11 525-line) */
#define XVID_PAR_169_PAL 4 /* 16:9 pal (16:11 625-line) */
#define XVID_PAR_169_NTSC 5 /* 16:9 ntsc (40:33 525-line) */
#define XVID_PAR_EXT 15 /* extended par; use par_width, par_height */
/* frame type flags */
#define XVID_TYPE_VOL -1 /* decoder only: vol was decoded */
#define XVID_TYPE_NOTHING 0 /* decoder only (encoder stats): nothing was decoded/encoded */
#define XVID_TYPE_AUTO 0 /* encoder: automatically determine coding type */
#define XVID_TYPE_IVOP 1 /* intra frame */
#define XVID_TYPE_PVOP 2 /* predicted frame */
#define XVID_TYPE_BVOP 3 /* bidirectionally encoded */
#define XVID_TYPE_SVOP 4 /* predicted+sprite frame */
/*****************************************************************************
* xvid_global()
****************************************************************************/
/* cpu_flags definitions (make sure to sync this with cpuid.asm for ia32) */
#define XVID_CPU_FORCE (1<<31) /* force passed cpu flags */
#define XVID_CPU_ASM (1<< 7) /* native assembly */
/* ARCH_IS_IA32 */
#define XVID_CPU_MMX (1<< 0) /* mmx : pentiumMMX,k6 */
#define XVID_CPU_MMXEXT (1<< 1) /* mmx-ext : pentium2, athlon */
#define XVID_CPU_SSE (1<< 2) /* sse : pentium3, athlonXP */
#define XVID_CPU_SSE2 (1<< 3) /* sse2 : pentium4, athlon64 */
#define XVID_CPU_3DNOW (1<< 4) /* 3dnow : k6-2 */
#define XVID_CPU_3DNOWEXT (1<< 5) /* 3dnow-ext : athlon */
#define XVID_CPU_TSC (1<< 6) /* tsc : Pentium */
/* ARCH_IS_PPC */
#define XVID_CPU_ALTIVEC (1<< 0) /* altivec */
#define XVID_DEBUG_ERROR (1<< 0)
#define XVID_DEBUG_STARTCODE (1<< 1)
#define XVID_DEBUG_HEADER (1<< 2)
#define XVID_DEBUG_TIMECODE (1<< 3)
#define XVID_DEBUG_MB (1<< 4)
#define XVID_DEBUG_COEFF (1<< 5)
#define XVID_DEBUG_MV (1<< 6)
#define XVID_DEBUG_RC (1<< 7)
#define XVID_DEBUG_DEBUG (1<<31)
/* XVID_GBL_INIT param1 */
typedef struct {
int version;
unsigned int cpu_flags; /* [in:opt] zero = autodetect cpu; XVID_CPU_FORCE|{cpu features} = force cpu features */
int debug; /* [in:opt] debug level */
} xvid_gbl_init_t;
/* XVID_GBL_INFO param1 */
typedef struct {
int version;
int actual_version; /* [out] returns the actual xvidcore version */
const char * build; /* [out] if !null, points to description of this xvid core build */
unsigned int cpu_flags; /* [out] detected cpu features */
int num_threads; /* [out] detected number of cpus/threads */
} xvid_gbl_info_t;
/* XVID_GBL_CONVERT param1 */
typedef struct {
int version;
xvid_image_t input; /* [in] input image & colorspace */
xvid_image_t output; /* [in] output image & colorspace */
int width; /* [in] width */
int height; /* [in] height */
int interlacing; /* [in] interlacing */
} xvid_gbl_convert_t;
#define XVID_GBL_INIT 0 /* initialize xvidcore; must be called before using xvid_decore, or xvid_encore) */
#define XVID_GBL_INFO 1 /* return some info about xvidcore, and the host computer */
#define XVID_GBL_CONVERT 2 /* colorspace conversion utility */
extern int xvid_global(void *handle, int opt, void *param1, void *param2);
/*****************************************************************************
* xvid_decore()
****************************************************************************/
#define XVID_DEC_CREATE 0 /* create decore instance; return 0 on success */
#define XVID_DEC_DESTROY 1 /* destroy decore instance: return 0 on success */
#define XVID_DEC_DECODE 2 /* decode a frame: returns number of bytes consumed >= 0 */
extern int xvid_decore(void *handle, int opt, void *param1, void *param2);
/* XVID_DEC_CREATE param 1
image width & height may be specified here when the dimensions are
known in advance. */
typedef struct {
int version;
int width; /* [in:opt] image width */
int height; /* [in:opt] image width */
void * handle; /* [out] decore context handle */
} xvid_dec_create_t;
/* XVID_DEC_DECODE param1 */
/* general flags */
#define XVID_LOWDELAY (1<<0) /* lowdelay mode */
#define XVID_DISCONTINUITY (1<<1) /* indicates break in stream */
#define XVID_DEBLOCKY (1<<2) /* perform luma deblocking */
#define XVID_DEBLOCKUV (1<<3) /* perform chroma deblocking */
#define XVID_FILMEFFECT (1<<4) /* adds film grain */
#define XVID_DERINGUV (1<<5) /* perform chroma deringing, requires deblocking to work */
#define XVID_DERINGY (1<<6) /* perform luma deringing, requires deblocking to work */
#define XVID_DEC_FAST (1<<29) /* disable postprocessing to decrease cpu usage *todo* */
#define XVID_DEC_DROP (1<<30) /* drop bframes to decrease cpu usage *todo* */
#define XVID_DEC_PREROLL (1<<31) /* decode as fast as you can, don't even show output *todo* */
typedef struct {
int version;
int general; /* [in:opt] general flags */
void *bitstream; /* [in] bitstream (read from)*/
int length; /* [in] bitstream length */
xvid_image_t output; /* [in] output image (written to) */
/* ------- v1.1.x ------- */
int brightness; /* [in] brightness offset (0=none) */
} xvid_dec_frame_t;
/* XVID_DEC_DECODE param2 :: optional */
typedef struct
{
int version;
int type; /* [out] output data type */
union {
struct { /* type>0 {XVID_TYPE_IVOP,XVID_TYPE_PVOP,XVID_TYPE_BVOP,XVID_TYPE_SVOP} */
int general; /* [out] flags */
int time_base; /* [out] time base */
int time_increment; /* [out] time increment */
/* XXX: external deblocking stuff */
int * qscale; /* [out] pointer to quantizer table */
int qscale_stride; /* [out] quantizer scale stride */
} vop;
struct { /* XVID_TYPE_VOL */
int general; /* [out] flags */
int width; /* [out] width */
int height; /* [out] height */
int par; /* [out] pixel aspect ratio (refer to XVID_PAR_xxx above) */
int par_width; /* [out] aspect ratio width [1..255] */
int par_height; /* [out] aspect ratio height [1..255] */
} vol;
} data;
} xvid_dec_stats_t;
#define XVID_ZONE_QUANT (1<<0)
#define XVID_ZONE_WEIGHT (1<<1)
typedef struct
{
int frame;
int mode;
int increment;
int base;
} xvid_enc_zone_t;
/*----------------------------------------------------------------------------
* xvid_enc_stats_t structure
*
* Used in:
* - xvid_plg_data_t structure
* - optional parameter in xvid_encore() function
*
* .coding_type = XVID_TYPE_NOTHING if the stats are not given
*--------------------------------------------------------------------------*/
typedef struct {
int version;
/* encoding parameters */
int type; /* [out] coding type */
int quant; /* [out] frame quantizer */
int vol_flags; /* [out] vol flags (see above) */
int vop_flags; /* [out] vop flags (see above) */
/* bitrate */
int length; /* [out] frame length */
int hlength; /* [out] header length (bytes) */
int kblks; /* [out] number of blocks compressed as Intra */
int mblks; /* [out] number of blocks compressed as Inter */
int ublks; /* [out] number of blocks marked as not_coded */
int sse_y; /* [out] Y plane's sse */
int sse_u; /* [out] U plane's sse */
int sse_v; /* [out] V plane's sse */
} xvid_enc_stats_t;
/*****************************************************************************
xvid plugin system -- internals
xvidcore will call XVID_PLG_INFO and XVID_PLG_CREATE during XVID_ENC_CREATE
before encoding each frame xvidcore will call XVID_PLG_BEFORE
after encoding each frame xvidcore will call XVID_PLG_AFTER
xvidcore will call XVID_PLG_DESTROY during XVID_ENC_DESTROY
****************************************************************************/
#define XVID_PLG_CREATE (1<<0)
#define XVID_PLG_DESTROY (1<<1)
#define XVID_PLG_INFO (1<<2)
#define XVID_PLG_BEFORE (1<<3)
#define XVID_PLG_FRAME (1<<4)
#define XVID_PLG_AFTER (1<<5)
/* xvid_plg_info_t.flags */
#define XVID_REQORIGINAL (1<<0) /* plugin requires a copy of the original (uncompressed) image */
#define XVID_REQPSNR (1<<1) /* plugin requires psnr between the uncompressed and compressed image*/
#define XVID_REQDQUANTS (1<<2) /* plugin requires access to the dquant table */
typedef struct
{
int version;
int flags; /* [in:opt] plugin flags */
} xvid_plg_info_t;
typedef struct
{
int version;
int num_zones; /* [out] */
xvid_enc_zone_t * zones; /* [out] */
int width; /* [out] */
int height; /* [out] */
int mb_width; /* [out] */
int mb_height; /* [out] */
int fincr; /* [out] */
int fbase; /* [out] */
void * param; /* [out] */
} xvid_plg_create_t;
typedef struct
{
int version;
int num_frames; /* [out] total frame encoded */
} xvid_plg_destroy_t;
typedef struct
{
int version;
xvid_enc_zone_t * zone; /* [out] current zone */
int width; /* [out] */
int height; /* [out] */
int mb_width; /* [out] */
int mb_height; /* [out] */
int fincr; /* [out] */
int fbase; /* [out] */
int min_quant[3]; /* [out] */
int max_quant[3]; /* [out] */
xvid_image_t reference; /* [out] -> [out] */
xvid_image_t current; /* [out] -> [in,out] */
xvid_image_t original; /* [out] after: points the original (uncompressed) copy of the current frame */
int frame_num; /* [out] frame number */
int type; /* [in,out] */
int quant; /* [in,out] */
int * dquant; /* [in,out] pointer to diff quantizer table */
int dquant_stride; /* [in,out] diff quantizer stride */
int vop_flags; /* [in,out] */
int vol_flags; /* [in,out] */
int motion_flags; /* [in,out] */
/* Deprecated, use the stats field instead.
* Will disapear before 1.0 */
int length; /* [out] after: length of encoded frame */
int kblks; /* [out] number of blocks compressed as Intra */
int mblks; /* [out] number of blocks compressed as Inter */
int ublks; /* [out] number of blocks marked not_coded */
int sse_y; /* [out] Y plane's sse */
int sse_u; /* [out] U plane's sse */
int sse_v; /* [out] V plane's sse */
/* End of duplicated data, kept only for binary compatibility */
int bquant_ratio; /* [in] */
int bquant_offset; /* [in] */
xvid_enc_stats_t stats; /* [out] frame statistics */
} xvid_plg_data_t;
/*****************************************************************************
xvid plugin system -- external
the application passes xvid an array of "xvid_plugin_t" at XVID_ENC_CREATE. the array
indicates the plugin function pointer and plugin-specific data.
xvidcore handles the rest. example:
xvid_enc_create_t create;
xvid_enc_plugin_t plugins[2];
plugins[0].func = xvid_psnr_func;
plugins[0].param = NULL;
plugins[1].func = xvid_cbr_func;
plugins[1].param = &cbr_data;
create.num_plugins = 2;
create.plugins = plugins;
****************************************************************************/
typedef int (xvid_plugin_func)(void * handle, int opt, void * param1, void * param2);
typedef struct
{
xvid_plugin_func * func;
void * param;
} xvid_enc_plugin_t;
extern xvid_plugin_func xvid_plugin_single; /* single-pass rate control */
extern xvid_plugin_func xvid_plugin_2pass1; /* two-pass rate control: first pass */
extern xvid_plugin_func xvid_plugin_2pass2; /* two-pass rate control: second pass */
extern xvid_plugin_func xvid_plugin_lumimasking; /* lumimasking */
extern xvid_plugin_func xvid_plugin_psnr; /* write psnr values to stdout */
extern xvid_plugin_func xvid_plugin_dump; /* dump before and after yuvpgms */
/* single pass rate control
* CBR and Constant quantizer modes */
typedef struct
{
int version;
int bitrate; /* [in] bits per second */
int reaction_delay_factor; /* [in] */
int averaging_period; /* [in] */
int buffer; /* [in] */
} xvid_plugin_single_t;
typedef struct {
int version;
char * filename;
} xvid_plugin_2pass1_t;
#define XVID_PAYBACK_BIAS 0 /* payback with bias */
#define XVID_PAYBACK_PROP 1 /* payback proportionally */
typedef struct {
int version;
int bitrate; /* [in] target bitrate (bits per second) */
char * filename; /* [in] first pass stats filename */
int keyframe_boost; /* [in] keyframe boost percentage: [0..100] */
int curve_compression_high; /* [in] percentage of compression performed on the high part of the curve (above average) */
int curve_compression_low; /* [in] percentage of compression performed on the low part of the curve (below average) */
int overflow_control_strength;/* [in] Payback delay expressed in number of frames */
int max_overflow_improvement; /* [in] percentage of allowed range for a frame that gets bigger because of overflow bonus */
int max_overflow_degradation; /* [in] percentage of allowed range for a frame that gets smaller because of overflow penalty */
int kfreduction; /* [in] maximum bitrate reduction applied to an iframe under the kfthreshold distance limit */
int kfthreshold; /* [in] if an iframe is closer to the next iframe than this distance, a quantity of bits
* is substracted from its bit allocation. The reduction is computed as multiples of
* kfreduction/kthreshold. It reaches kfreduction when the distance == kfthreshold,
* 0 for 1<distance<kfthreshold */
int container_frame_overhead; /* [in] How many bytes the controller has to compensate per frame due to container format overhead */
/* ------- v1.1.x ------- */
int vbv_size; /* [in] buffer size (bits) */
int vbv_initial; /* [in] initial buffer occupancy (bits) */
int vbv_maxrate; /* [in] max processing bitrate (bits per second) */
int vbv_peakrate; /* [in:opt] max average bitrate over 3 seconds (bits per second) */
}xvid_plugin_2pass2_t;
/*****************************************************************************
* ENCODER API
****************************************************************************/
/*----------------------------------------------------------------------------
* Encoder operations
*--------------------------------------------------------------------------*/
#define XVID_ENC_CREATE 0 /* create encoder instance; returns 0 on success */
#define XVID_ENC_DESTROY 1 /* destroy encoder instance; returns 0 on success */
#define XVID_ENC_ENCODE 2 /* encode a frame: returns number of ouput bytes
* 0 means this frame should not be written (ie. encoder lag) */
/*----------------------------------------------------------------------------
* Encoder entry point
*--------------------------------------------------------------------------*/
extern int xvid_encore(void *handle, int opt, void *param1, void *param2);
/* Quick API reference
*
* XVID_ENC_CREATE operation
* - handle: ignored
* - opt: XVID_ENC_CREATE
* - param1: address of a xvid_enc_create_t structure
* - param2: ignored
*
* XVID_ENC_ENCODE operation
* - handle: an instance returned by a CREATE op
* - opt: XVID_ENC_ENCODE
* - param1: address of a xvid_enc_frame_t structure
* - param2: address of a xvid_enc_stats_t structure (optional)
* its return value is asynchronous to what is written to the buffer
* depending on the delay introduced by bvop use. It's display
* ordered.
*
* XVID_ENC_DESTROY operation
* - handle: an instance returned by a CREATE op
* - opt: XVID_ENC_DESTROY
* - param1: ignored
* - param2: ignored
*/
/*----------------------------------------------------------------------------
* "Global" flags
*
* These flags are used for xvid_enc_create_t->global field during instance
* creation (operation XVID_ENC_CREATE)
*--------------------------------------------------------------------------*/
#define XVID_GLOBAL_PACKED (1<<0) /* packed bitstream */
#define XVID_GLOBAL_CLOSED_GOP (1<<1) /* closed_gop: was DX50BVOP dx50 bvop compatibility */
#define XVID_GLOBAL_EXTRASTATS_ENABLE (1<<2)
#if 0
#define XVID_GLOBAL_VOL_AT_IVOP (1<<3) /* write vol at every ivop: WIN32/divx compatibility */
#define XVID_GLOBAL_FORCE_VOL (1<<4) /* when vol-based parameters are changed, insert an ivop NOT recommended */
#endif
#define XVID_GLOBAL_DIVX5_USERDATA (1<<5) /* write divx5 userdata string
this is implied if XVID_GLOBAL_PACKED is set */
/*----------------------------------------------------------------------------
* "VOL" flags
*
* These flags are used for xvid_enc_frame_t->vol_flags field during frame
* encoding (operation XVID_ENC_ENCODE)
*--------------------------------------------------------------------------*/
#define XVID_VOL_MPEGQUANT (1<<0) /* enable MPEG type quantization */
#define XVID_VOL_EXTRASTATS (1<<1) /* enable plane sse stats */
#define XVID_VOL_QUARTERPEL (1<<2) /* enable quarterpel: frames will encoded as quarterpel */
#define XVID_VOL_GMC (1<<3) /* enable GMC; frames will be checked for gmc suitability */
#define XVID_VOL_REDUCED_ENABLE (1<<4) /* enable reduced resolution vops: frames will be checked for rrv suitability */
/* NOTE: the reduced resolution feature is not supported anymore. This flag will have no effect! */
#define XVID_VOL_INTERLACING (1<<5) /* enable interlaced encoding */
/*----------------------------------------------------------------------------
* "VOP" flags
*
* These flags are used for xvid_enc_frame_t->vop_flags field during frame
* encoding (operation XVID_ENC_ENCODE)
*--------------------------------------------------------------------------*/
/* Always valid */
#define XVID_VOP_DEBUG (1<< 0) /* print debug messages in frames */
#define XVID_VOP_HALFPEL (1<< 1) /* use halfpel interpolation */
#define XVID_VOP_INTER4V (1<< 2) /* use 4 motion vectors per MB */
#define XVID_VOP_TRELLISQUANT (1<< 3) /* use trellis based R-D "optimal" quantization */
#define XVID_VOP_CHROMAOPT (1<< 4) /* enable chroma optimization pre-filter */
#define XVID_VOP_CARTOON (1<< 5) /* use 'cartoon mode' */
#define XVID_VOP_GREYSCALE (1<< 6) /* enable greyscale only mode (even for color input material chroma is ignored) */
#define XVID_VOP_HQACPRED (1<< 7) /* high quality ac prediction */
#define XVID_VOP_MODEDECISION_RD (1<< 8) /* enable DCT-ME and use it for mode decision */
#define XVID_VOP_FAST_MODEDECISION_RD (1<<12) /* use simplified R-D mode decision */
#define XVID_VOP_RD_BVOP (1<<13) /* enable rate-distortion mode decision in b-frames */
/* Only valid for vol_flags|=XVID_VOL_INTERLACING */
#define XVID_VOP_TOPFIELDFIRST (1<< 9) /* set top-field-first flag */
#define XVID_VOP_ALTERNATESCAN (1<<10) /* set alternate vertical scan flag */
/* only valid for vol_flags|=XVID_VOL_REDUCED_ENABLED */
#define XVID_VOP_REDUCED (1<<11) /* reduced resolution vop */
/* NOTE: reduced resolution feature is not supported anymore. This flag will have no effect! */
/*----------------------------------------------------------------------------
* "Motion" flags
*
* These flags are used for xvid_enc_frame_t->motion field during frame
* encoding (operation XVID_ENC_ENCODE)
*--------------------------------------------------------------------------*/
/* Motion Estimation Search Patterns */
#define XVID_ME_ADVANCEDDIAMOND16 (1<< 0) /* use advdiamonds instead of diamonds as search pattern */
#define XVID_ME_ADVANCEDDIAMOND8 (1<< 1) /* use advdiamond for XVID_ME_EXTSEARCH8 */
#define XVID_ME_USESQUARES16 (1<< 2) /* use squares instead of diamonds as search pattern */
#define XVID_ME_USESQUARES8 (1<< 3) /* use square for XVID_ME_EXTSEARCH8 */
/* SAD operator based flags */
#define XVID_ME_HALFPELREFINE16 (1<< 4)
#define XVID_ME_HALFPELREFINE8 (1<< 6)
#define XVID_ME_QUARTERPELREFINE16 (1<< 7)
#define XVID_ME_QUARTERPELREFINE8 (1<< 8)
#define XVID_ME_GME_REFINE (1<< 9)
#define XVID_ME_EXTSEARCH16 (1<<10) /* extend PMV by more searches */
#define XVID_ME_EXTSEARCH8 (1<<11) /* use diamond/square for extended 8x8 search */
#define XVID_ME_CHROMA_PVOP (1<<12) /* also use chroma for P_VOP/S_VOP ME */
#define XVID_ME_CHROMA_BVOP (1<<13) /* also use chroma for B_VOP ME */
#define XVID_ME_FASTREFINE16 (1<<25) /* use low-complexity refinement functions */
#define XVID_ME_FASTREFINE8 (1<<29) /* low-complexity 8x8 sub-block refinement */
/* Rate Distortion based flags
* Valid when XVID_VOP_MODEDECISION_RD is enabled */
#define XVID_ME_HALFPELREFINE16_RD (1<<14) /* perform RD-based halfpel refinement */
#define XVID_ME_HALFPELREFINE8_RD (1<<15) /* perform RD-based halfpel refinement for 8x8 mode */
#define XVID_ME_QUARTERPELREFINE16_RD (1<<16) /* perform RD-based qpel refinement */
#define XVID_ME_QUARTERPELREFINE8_RD (1<<17) /* perform RD-based qpel refinement for 8x8 mode */
#define XVID_ME_EXTSEARCH_RD (1<<18) /* perform RD-based search using square pattern enable XVID_ME_EXTSEARCH8 to do this in 8x8 search as well */
#define XVID_ME_CHECKPREDICTION_RD (1<<19) /* always check vector equal to prediction */
/* Other */
#define XVID_ME_DETECT_STATIC_MOTION (1<<24) /* speed-up ME by detecting stationary scenes */
#define XVID_ME_SKIP_DELTASEARCH (1<<26) /* speed-up by skipping b-frame delta search */
#define XVID_ME_FAST_MODEINTERPOLATE (1<<27) /* speed-up by partly skipping interpolate mode */
#define XVID_ME_BFRAME_EARLYSTOP (1<<28) /* speed-up by early exiting b-search */
/* Unused */
#define XVID_ME_UNRESTRICTED16 (1<<20) /* unrestricted ME, not implemented */
#define XVID_ME_OVERLAPPING16 (1<<21) /* overlapping ME, not implemented */
#define XVID_ME_UNRESTRICTED8 (1<<22) /* unrestricted ME, not implemented */
#define XVID_ME_OVERLAPPING8 (1<<23) /* overlapping ME, not implemented */
/*----------------------------------------------------------------------------
* xvid_enc_create_t structure definition
*
* This structure is passed as param1 during an instance creation (operation
* XVID_ENC_CREATE)
*--------------------------------------------------------------------------*/
typedef struct {
int version;
int profile; /* [in] profile@level; refer to XVID_PROFILE_xxx */
int width; /* [in] frame dimensions; width, pixel units */
int height; /* [in] frame dimensions; height, pixel units */
int num_zones; /* [in:opt] number of bitrate zones */
xvid_enc_zone_t * zones; /* ^^ zone array */
int num_plugins; /* [in:opt] number of plugins */
xvid_enc_plugin_t * plugins; /* ^^ plugin array */
int num_threads; /* [in:opt] number of threads */
int max_bframes; /* [in:opt] max sequential bframes (0=disable bframes) */
int global; /* [in:opt] global flags; controls encoding behavior */
/* --- vol-based stuff; included here for convenience */
int fincr; /* [in:opt] framerate increment; set to zero for variable framerate */
int fbase; /* [in] framerate base frame_duration = fincr/fbase seconds*/
/* ---------------------------------------------- */
/* --- vop-based; included here for convenience */
int max_key_interval; /* [in:opt] the maximum interval between key frames */
int frame_drop_ratio; /* [in:opt] frame dropping: 0=drop none... 100=drop all */
int bquant_ratio; /* [in:opt] bframe quantizer multipier/offeset; used to decide bframes quant when bquant==-1 */
int bquant_offset; /* bquant = (avg(past_ref_quant,future_ref_quant)*bquant_ratio + bquant_offset) / 100 */
int min_quant[3]; /* [in:opt] */
int max_quant[3]; /* [in:opt] */
/* ---------------------------------------------- */
void *handle; /* [out] encoder instance handle */
} xvid_enc_create_t;
/*----------------------------------------------------------------------------
* xvid_enc_frame_t structure definition
*
* This structure is passed as param1 during a frame encoding (operation
* XVID_ENC_ENCODE)
*--------------------------------------------------------------------------*/
/* out value for the frame structure->type field
* unlike stats output in param2, this field is not asynchronous and tells
* the client app, if the frame written into the stream buffer is an ivop
* usually used for indexing purpose in the container */
#define XVID_KEYFRAME (1<<1)
/* The structure */
typedef struct {
int version;
/* VOL related stuff
* unless XVID_FORCEVOL is set, the encoder will not react to any changes
* here until the next VOL (keyframe). */
int vol_flags; /* [in] vol flags */
unsigned char *quant_intra_matrix; /* [in:opt] custom intra qmatrix */
unsigned char *quant_inter_matrix; /* [in:opt] custom inter qmatrix */
int par; /* [in:opt] pixel aspect ratio (refer to XVID_PAR_xxx above) */
int par_width; /* [in:opt] aspect ratio width */
int par_height; /* [in:opt] aspect ratio height */
/* Other fields that can change on a frame base */
int fincr; /* [in:opt] framerate increment, for variable framerate only */
int vop_flags; /* [in] (general)vop-based flags */
int motion; /* [in] ME options */
xvid_image_t input; /* [in] input image (read from) */
int type; /* [in:opt] coding type */
int quant; /* [in] frame quantizer; if <=0, automatic (ratecontrol) */
int bframe_threshold;
void *bitstream; /* [in:opt] bitstream ptr (written to)*/
int length; /* [in:opt] bitstream length (bytes) */
int out_flags; /* [out] bitstream output flags */
} xvid_enc_frame_t;
#ifdef __cplusplus
}
#endif
#endif