Initial import
This commit is contained in:
commit
306e265019
72 changed files with 23271 additions and 0 deletions
911
BitstreamConverter.cpp
Normal file
911
BitstreamConverter.cpp
Normal file
|
|
@ -0,0 +1,911 @@
|
|||
/*
|
||||
* Copyright (C) 2010 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef UINT16_MAX
|
||||
#define UINT16_MAX (65535U)
|
||||
#endif
|
||||
|
||||
#include "BitstreamConverter.h"
|
||||
|
||||
void CBitstreamConverter::bits_reader_set( bits_reader_t *br, uint8_t *buf, int len )
|
||||
{
|
||||
br->buffer = br->start = buf;
|
||||
br->offbits = 0;
|
||||
br->length = len;
|
||||
br->oflow = 0;
|
||||
}
|
||||
|
||||
uint32_t CBitstreamConverter::read_bits( bits_reader_t *br, int nbits )
|
||||
{
|
||||
int i, nbytes;
|
||||
uint32_t ret = 0;
|
||||
uint8_t *buf;
|
||||
|
||||
buf = br->buffer;
|
||||
nbytes = (br->offbits + nbits)/8;
|
||||
if ( ((br->offbits + nbits) %8 ) > 0 )
|
||||
nbytes++;
|
||||
if ( (buf + nbytes) > (br->start + br->length) ) {
|
||||
br->oflow = 1;
|
||||
return 0;
|
||||
}
|
||||
for ( i=0; i<nbytes; i++ )
|
||||
ret += buf[i]<<((nbytes-i-1)*8);
|
||||
i = (4-nbytes)*8+br->offbits;
|
||||
ret = ((ret<<i)>>i)>>((nbytes*8)-nbits-br->offbits);
|
||||
|
||||
br->offbits += nbits;
|
||||
br->buffer += br->offbits / 8;
|
||||
br->offbits %= 8;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CBitstreamConverter::skip_bits( bits_reader_t *br, int nbits )
|
||||
{
|
||||
br->offbits += nbits;
|
||||
br->buffer += br->offbits / 8;
|
||||
br->offbits %= 8;
|
||||
if ( br->buffer > (br->start + br->length) ) {
|
||||
br->oflow = 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t CBitstreamConverter::get_bits( bits_reader_t *br, int nbits )
|
||||
{
|
||||
int i, nbytes;
|
||||
uint32_t ret = 0;
|
||||
uint8_t *buf;
|
||||
|
||||
buf = br->buffer;
|
||||
nbytes = (br->offbits + nbits)/8;
|
||||
if ( ((br->offbits + nbits) %8 ) > 0 )
|
||||
nbytes++;
|
||||
if ( (buf + nbytes) > (br->start + br->length) ) {
|
||||
br->oflow = 1;
|
||||
return 0;
|
||||
}
|
||||
for ( i=0; i<nbytes; i++ )
|
||||
ret += buf[i]<<((nbytes-i-1)*8);
|
||||
i = (4-nbytes)*8+br->offbits;
|
||||
ret = ((ret<<i)>>i)>>((nbytes*8)-nbits-br->offbits);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// GStreamer h264 parser
|
||||
// Copyright (C) 2005 Michal Benes <michal.benes@itonis.tv>
|
||||
// (C) 2008 Wim Taymans <wim.taymans@gmail.com>
|
||||
// gsth264parse.c:
|
||||
// * License as published by the Free Software Foundation; either
|
||||
// * version 2.1 of the License, or (at your option) any later version.
|
||||
void CBitstreamConverter::nal_bs_init(nal_bitstream *bs, const uint8_t *data, size_t size)
|
||||
{
|
||||
bs->data = data;
|
||||
bs->end = data + size;
|
||||
bs->head = 0;
|
||||
// fill with something other than 0 to detect
|
||||
// emulation prevention bytes
|
||||
bs->cache = 0xffffffff;
|
||||
}
|
||||
|
||||
uint32_t CBitstreamConverter::nal_bs_read(nal_bitstream *bs, int n)
|
||||
{
|
||||
uint32_t res = 0;
|
||||
int shift;
|
||||
|
||||
if (n == 0)
|
||||
return res;
|
||||
|
||||
// fill up the cache if we need to
|
||||
while (bs->head < n)
|
||||
{
|
||||
uint8_t a_byte;
|
||||
bool check_three_byte;
|
||||
|
||||
check_three_byte = true;
|
||||
next_byte:
|
||||
if (bs->data >= bs->end)
|
||||
{
|
||||
// we're at the end, can't produce more than head number of bits
|
||||
n = bs->head;
|
||||
break;
|
||||
}
|
||||
// get the byte, this can be an emulation_prevention_three_byte that we need
|
||||
// to ignore.
|
||||
a_byte = *bs->data++;
|
||||
if (check_three_byte && a_byte == 0x03 && ((bs->cache & 0xffff) == 0))
|
||||
{
|
||||
// next byte goes unconditionally to the cache, even if it's 0x03
|
||||
check_three_byte = false;
|
||||
goto next_byte;
|
||||
}
|
||||
// shift bytes in cache, moving the head bits of the cache left
|
||||
bs->cache = (bs->cache << 8) | a_byte;
|
||||
bs->head += 8;
|
||||
}
|
||||
|
||||
// bring the required bits down and truncate
|
||||
if ((shift = bs->head - n) > 0)
|
||||
res = bs->cache >> shift;
|
||||
else
|
||||
res = bs->cache;
|
||||
|
||||
// mask out required bits
|
||||
if (n < 32)
|
||||
res &= (1 << n) - 1;
|
||||
bs->head = shift;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool CBitstreamConverter::nal_bs_eos(nal_bitstream *bs)
|
||||
{
|
||||
return (bs->data >= bs->end) && (bs->head == 0);
|
||||
}
|
||||
|
||||
// read unsigned Exp-Golomb code
|
||||
int CBitstreamConverter::nal_bs_read_ue(nal_bitstream *bs)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (nal_bs_read(bs, 1) == 0 && !nal_bs_eos(bs) && i < 32)
|
||||
i++;
|
||||
|
||||
return ((1 << i) - 1 + nal_bs_read(bs, i));
|
||||
}
|
||||
|
||||
void CBitstreamConverter::parseh264_sps(uint8_t *sps, uint32_t sps_size, bool *interlaced, int32_t *max_ref_frames)
|
||||
{
|
||||
nal_bitstream bs;
|
||||
sps_info_struct sps_info;
|
||||
|
||||
nal_bs_init(&bs, sps, sps_size);
|
||||
|
||||
sps_info.profile_idc = nal_bs_read(&bs, 8);
|
||||
nal_bs_read(&bs, 1); // constraint_set0_flag
|
||||
nal_bs_read(&bs, 1); // constraint_set1_flag
|
||||
nal_bs_read(&bs, 1); // constraint_set2_flag
|
||||
nal_bs_read(&bs, 1); // constraint_set3_flag
|
||||
nal_bs_read(&bs, 4); // reserved
|
||||
sps_info.level_idc = nal_bs_read(&bs, 8);
|
||||
sps_info.sps_id = nal_bs_read_ue(&bs);
|
||||
|
||||
if (sps_info.profile_idc == 100 ||
|
||||
sps_info.profile_idc == 110 ||
|
||||
sps_info.profile_idc == 122 ||
|
||||
sps_info.profile_idc == 244 ||
|
||||
sps_info.profile_idc == 44 ||
|
||||
sps_info.profile_idc == 83 ||
|
||||
sps_info.profile_idc == 86)
|
||||
{
|
||||
sps_info.chroma_format_idc = nal_bs_read_ue(&bs);
|
||||
if (sps_info.chroma_format_idc == 3)
|
||||
sps_info.separate_colour_plane_flag = nal_bs_read(&bs, 1);
|
||||
sps_info.bit_depth_luma_minus8 = nal_bs_read_ue(&bs);
|
||||
sps_info.bit_depth_chroma_minus8 = nal_bs_read_ue(&bs);
|
||||
sps_info.qpprime_y_zero_transform_bypass_flag = nal_bs_read(&bs, 1);
|
||||
|
||||
sps_info.seq_scaling_matrix_present_flag = nal_bs_read (&bs, 1);
|
||||
if (sps_info.seq_scaling_matrix_present_flag)
|
||||
{
|
||||
/* TODO: unfinished */
|
||||
}
|
||||
}
|
||||
sps_info.log2_max_frame_num_minus4 = nal_bs_read_ue(&bs);
|
||||
if (sps_info.log2_max_frame_num_minus4 > 12)
|
||||
{ // must be between 0 and 12
|
||||
return;
|
||||
}
|
||||
sps_info.pic_order_cnt_type = nal_bs_read_ue(&bs);
|
||||
if (sps_info.pic_order_cnt_type == 0)
|
||||
{
|
||||
sps_info.log2_max_pic_order_cnt_lsb_minus4 = nal_bs_read_ue(&bs);
|
||||
}
|
||||
else if (sps_info.pic_order_cnt_type == 1)
|
||||
{ // TODO: unfinished
|
||||
/*
|
||||
delta_pic_order_always_zero_flag = gst_nal_bs_read (bs, 1);
|
||||
offset_for_non_ref_pic = gst_nal_bs_read_se (bs);
|
||||
offset_for_top_to_bottom_field = gst_nal_bs_read_se (bs);
|
||||
|
||||
num_ref_frames_in_pic_order_cnt_cycle = gst_nal_bs_read_ue (bs);
|
||||
for( i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++ )
|
||||
offset_for_ref_frame[i] = gst_nal_bs_read_se (bs);
|
||||
*/
|
||||
}
|
||||
|
||||
sps_info.max_num_ref_frames = nal_bs_read_ue(&bs);
|
||||
sps_info.gaps_in_frame_num_value_allowed_flag = nal_bs_read(&bs, 1);
|
||||
sps_info.pic_width_in_mbs_minus1 = nal_bs_read_ue(&bs);
|
||||
sps_info.pic_height_in_map_units_minus1 = nal_bs_read_ue(&bs);
|
||||
|
||||
sps_info.frame_mbs_only_flag = nal_bs_read(&bs, 1);
|
||||
if (!sps_info.frame_mbs_only_flag)
|
||||
sps_info.mb_adaptive_frame_field_flag = nal_bs_read(&bs, 1);
|
||||
|
||||
sps_info.direct_8x8_inference_flag = nal_bs_read(&bs, 1);
|
||||
|
||||
sps_info.frame_cropping_flag = nal_bs_read(&bs, 1);
|
||||
if (sps_info.frame_cropping_flag)
|
||||
{
|
||||
sps_info.frame_crop_left_offset = nal_bs_read_ue(&bs);
|
||||
sps_info.frame_crop_right_offset = nal_bs_read_ue(&bs);
|
||||
sps_info.frame_crop_top_offset = nal_bs_read_ue(&bs);
|
||||
sps_info.frame_crop_bottom_offset = nal_bs_read_ue(&bs);
|
||||
}
|
||||
|
||||
*interlaced = !sps_info.frame_mbs_only_flag;
|
||||
*max_ref_frames = sps_info.max_num_ref_frames;
|
||||
}
|
||||
|
||||
const uint8_t *CBitstreamConverter::avc_find_startcode_internal(const uint8_t *p, const uint8_t *end)
|
||||
{
|
||||
const uint8_t *a = p + 4 - ((intptr_t)p & 3);
|
||||
|
||||
for (end -= 3; p < a && p < end; p++)
|
||||
{
|
||||
if (p[0] == 0 && p[1] == 0 && p[2] == 1)
|
||||
return p;
|
||||
}
|
||||
|
||||
for (end -= 3; p < end; p += 4)
|
||||
{
|
||||
uint32_t x = *(const uint32_t*)p;
|
||||
if ((x - 0x01010101) & (~x) & 0x80808080) // generic
|
||||
{
|
||||
if (p[1] == 0)
|
||||
{
|
||||
if (p[0] == 0 && p[2] == 1)
|
||||
return p;
|
||||
if (p[2] == 0 && p[3] == 1)
|
||||
return p+1;
|
||||
}
|
||||
if (p[3] == 0)
|
||||
{
|
||||
if (p[2] == 0 && p[4] == 1)
|
||||
return p+2;
|
||||
if (p[4] == 0 && p[5] == 1)
|
||||
return p+3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (end += 3; p < end; p++)
|
||||
{
|
||||
if (p[0] == 0 && p[1] == 0 && p[2] == 1)
|
||||
return p;
|
||||
}
|
||||
|
||||
return end + 3;
|
||||
}
|
||||
|
||||
const uint8_t *CBitstreamConverter::avc_find_startcode(const uint8_t *p, const uint8_t *end)
|
||||
{
|
||||
const uint8_t *out= avc_find_startcode_internal(p, end);
|
||||
if (p<out && out<end && !out[-1])
|
||||
out--;
|
||||
return out;
|
||||
}
|
||||
|
||||
const int CBitstreamConverter::avc_parse_nal_units(ByteIOContext *pb, const uint8_t *buf_in, int size)
|
||||
{
|
||||
const uint8_t *p = buf_in;
|
||||
const uint8_t *end = p + size;
|
||||
const uint8_t *nal_start, *nal_end;
|
||||
|
||||
size = 0;
|
||||
nal_start = avc_find_startcode(p, end);
|
||||
|
||||
for (;;) {
|
||||
while (nal_start < end && !*(nal_start++));
|
||||
if (nal_start == end)
|
||||
break;
|
||||
|
||||
nal_end = avc_find_startcode(nal_start, end);
|
||||
m_dllAvFormat->put_be32(pb, nal_end - nal_start);
|
||||
m_dllAvFormat->put_buffer(pb, nal_start, nal_end - nal_start);
|
||||
size += 4 + nal_end - nal_start;
|
||||
nal_start = nal_end;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
const int CBitstreamConverter::avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size)
|
||||
{
|
||||
ByteIOContext *pb;
|
||||
int ret = m_dllAvFormat->url_open_dyn_buf(&pb);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
avc_parse_nal_units(pb, buf_in, *size);
|
||||
|
||||
m_dllAvUtil->av_freep(buf);
|
||||
*size = m_dllAvFormat->url_close_dyn_buf(pb, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int CBitstreamConverter::isom_write_avcc(ByteIOContext *pb, const uint8_t *data, int len)
|
||||
{
|
||||
// extradata from bytestream h264, convert to avcC atom data for bitstream
|
||||
if (len > 6)
|
||||
{
|
||||
/* check for h264 start code */
|
||||
if (OMX_RB32(data) == 0x00000001 || OMX_RB24(data) == 0x000001)
|
||||
{
|
||||
uint8_t *buf=NULL, *end, *start;
|
||||
uint32_t sps_size=0, pps_size=0;
|
||||
uint8_t *sps=0, *pps=0;
|
||||
|
||||
int ret = avc_parse_nal_units_buf(data, &buf, &len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
start = buf;
|
||||
end = buf + len;
|
||||
|
||||
/* look for sps and pps */
|
||||
while (end - buf > 4)
|
||||
{
|
||||
uint32_t size;
|
||||
uint8_t nal_type;
|
||||
size = FFMIN(OMX_RB32(buf), end - buf - 4);
|
||||
buf += 4;
|
||||
nal_type = buf[0] & 0x1f;
|
||||
if (nal_type == 7) /* SPS */
|
||||
{
|
||||
sps = buf;
|
||||
sps_size = size;
|
||||
}
|
||||
else if (nal_type == 8) /* PPS */
|
||||
{
|
||||
pps = buf;
|
||||
pps_size = size;
|
||||
}
|
||||
buf += size;
|
||||
}
|
||||
if (!sps || !pps || sps_size < 4 || sps_size > UINT16_MAX || pps_size > UINT16_MAX)
|
||||
assert(0);
|
||||
|
||||
m_dllAvFormat->put_byte(pb, 1); /* version */
|
||||
m_dllAvFormat->put_byte(pb, sps[1]); /* profile */
|
||||
m_dllAvFormat->put_byte(pb, sps[2]); /* profile compat */
|
||||
m_dllAvFormat->put_byte(pb, sps[3]); /* level */
|
||||
m_dllAvFormat->put_byte(pb, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */
|
||||
m_dllAvFormat->put_byte(pb, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */
|
||||
|
||||
m_dllAvFormat->put_be16(pb, sps_size);
|
||||
m_dllAvFormat->put_buffer(pb, sps, sps_size);
|
||||
if (pps)
|
||||
{
|
||||
m_dllAvFormat->put_byte(pb, 1); /* number of pps */
|
||||
m_dllAvFormat->put_be16(pb, pps_size);
|
||||
m_dllAvFormat->put_buffer(pb, pps, pps_size);
|
||||
}
|
||||
m_dllAvUtil->av_free(start);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dllAvFormat->put_buffer(pb, data, len);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
CBitstreamConverter::CBitstreamConverter()
|
||||
{
|
||||
m_convert_bitstream = false;
|
||||
m_convertBuffer = NULL;
|
||||
m_convertSize = 0;
|
||||
m_inputBuffer = NULL;
|
||||
m_inputSize = 0;
|
||||
m_to_annexb = false;
|
||||
m_extradata = NULL;
|
||||
m_extrasize = 0;
|
||||
m_convert_3byteTo4byteNALSize = false;
|
||||
m_dllAvUtil = NULL;
|
||||
m_dllAvFormat = NULL;
|
||||
m_convert_bytestream = false;
|
||||
m_convert_vc1 = false;
|
||||
}
|
||||
|
||||
CBitstreamConverter::~CBitstreamConverter()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
bool CBitstreamConverter::Open(enum CodecID codec, uint8_t *in_extradata, int in_extrasize, bool to_annexb)
|
||||
{
|
||||
m_to_annexb = to_annexb;
|
||||
m_convert_vc1 = false;
|
||||
|
||||
m_codec = codec;
|
||||
|
||||
switch(codec)
|
||||
{
|
||||
case CODEC_ID_VC1:
|
||||
m_extradata = (uint8_t *)malloc(in_extrasize);
|
||||
memcpy(m_extradata, in_extradata, in_extrasize);
|
||||
m_extrasize = in_extrasize;
|
||||
m_dllAvUtil = new DllAvUtil;
|
||||
m_dllAvFormat = new DllAvFormat;
|
||||
if (!m_dllAvUtil->Load() || !m_dllAvFormat->Load())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
break;
|
||||
case CODEC_ID_H264:
|
||||
if (in_extrasize < 7 || in_extradata == NULL)
|
||||
{
|
||||
CLog::Log(LOGERROR, "CBitstreamConverter::Open avcC data too small or missing\n");
|
||||
return false;
|
||||
}
|
||||
// valid avcC data (bitstream) always starts with the value 1 (version)
|
||||
if(m_to_annexb)
|
||||
{
|
||||
if ( *(char*)in_extradata == 1 )
|
||||
{
|
||||
CLog::Log(LOGINFO, "CBitstreamConverter::Open bitstream to annexb init\n");
|
||||
m_convert_bitstream = BitstreamConvertInit(in_extradata, in_extrasize);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// valid avcC atom data always starts with the value 1 (version)
|
||||
if ( *in_extradata != 1 )
|
||||
{
|
||||
if (in_extradata[0] == 0 && in_extradata[1] == 0 && in_extradata[2] == 0 && in_extradata[3] == 1)
|
||||
{
|
||||
CLog::Log(LOGINFO, "CBitstreamConverter::Open annexb to bitstream init\n");
|
||||
// video content is from x264 or from bytestream h264 (AnnexB format)
|
||||
// NAL reformating to bitstream format needed
|
||||
m_dllAvUtil = new DllAvUtil;
|
||||
m_dllAvFormat = new DllAvFormat;
|
||||
if (!m_dllAvUtil->Load() || !m_dllAvFormat->Load())
|
||||
return false;
|
||||
|
||||
ByteIOContext *pb;
|
||||
if (m_dllAvFormat->url_open_dyn_buf(&pb) < 0)
|
||||
return false;
|
||||
m_convert_bytestream = true;
|
||||
// create a valid avcC atom data from ffmpeg's extradata
|
||||
isom_write_avcc(pb, in_extradata, in_extrasize);
|
||||
// unhook from ffmpeg's extradata
|
||||
in_extradata = NULL;
|
||||
// extract the avcC atom data into extradata then write it into avcCData for VDADecoder
|
||||
in_extrasize = m_dllAvFormat->url_close_dyn_buf(pb, &in_extradata);
|
||||
// make a copy of extradata contents
|
||||
m_extradata = (uint8_t *)malloc(in_extrasize);
|
||||
memcpy(m_extradata, in_extradata, in_extrasize);
|
||||
m_extrasize = in_extrasize;
|
||||
// done with the converted extradata, we MUST free using av_free
|
||||
m_dllAvUtil->av_free(in_extradata);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CLog::Log(LOGNOTICE, "CBitstreamConverter::Open invalid avcC atom data");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (in_extradata[4] == 0xFE)
|
||||
{
|
||||
CLog::Log(LOGINFO, "CBitstreamConverter::Open annexb to bitstream init 3 byte to 4 byte nal\n");
|
||||
// video content is from so silly encoder that think 3 byte NAL sizes
|
||||
// are valid, setup to convert 3 byte NAL sizes to 4 byte.
|
||||
m_dllAvUtil = new DllAvUtil;
|
||||
m_dllAvFormat = new DllAvFormat;
|
||||
if (!m_dllAvUtil->Load() || !m_dllAvFormat->Load())
|
||||
return false;
|
||||
|
||||
in_extradata[4] = 0xFF;
|
||||
m_convert_3byteTo4byteNALSize = true;
|
||||
|
||||
m_extradata = (uint8_t *)malloc(in_extrasize);
|
||||
memcpy(m_extradata, in_extradata, in_extrasize);
|
||||
m_extrasize = in_extrasize;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CBitstreamConverter::Close(void)
|
||||
{
|
||||
if (m_convert_bitstream)
|
||||
{
|
||||
if (m_sps_pps_context.sps_pps_data)
|
||||
{
|
||||
free(m_sps_pps_context.sps_pps_data);
|
||||
m_sps_pps_context.sps_pps_data = NULL;
|
||||
}
|
||||
if(m_convertBuffer)
|
||||
free(m_convertBuffer);
|
||||
m_convertSize = 0;
|
||||
}
|
||||
|
||||
if (m_convert_bytestream || m_convert_vc1)
|
||||
{
|
||||
if(m_convertBuffer)
|
||||
{
|
||||
m_dllAvUtil->av_free(m_convertBuffer);
|
||||
m_convertBuffer = NULL;
|
||||
}
|
||||
m_convertSize = 0;
|
||||
}
|
||||
|
||||
if(m_extradata)
|
||||
free(m_extradata);
|
||||
m_extradata = NULL;
|
||||
m_extrasize = 0;
|
||||
|
||||
m_inputBuffer = NULL;
|
||||
m_inputSize = 0;
|
||||
m_convert_3byteTo4byteNALSize = false;
|
||||
|
||||
m_convert_bitstream = false;
|
||||
|
||||
if (m_dllAvUtil)
|
||||
{
|
||||
delete m_dllAvUtil;
|
||||
m_dllAvUtil = NULL;
|
||||
}
|
||||
if (m_dllAvFormat)
|
||||
{
|
||||
delete m_dllAvFormat;
|
||||
m_dllAvFormat = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool CBitstreamConverter::Convert(uint8_t *pData, int iSize)
|
||||
{
|
||||
if(m_convertBuffer)
|
||||
free(m_convertBuffer);
|
||||
m_convertBuffer = NULL;
|
||||
m_convertSize = 0;
|
||||
m_inputBuffer = NULL;
|
||||
m_inputSize = 0;
|
||||
|
||||
if (pData)
|
||||
{
|
||||
if(m_codec == CODEC_ID_H264)
|
||||
{
|
||||
if(m_to_annexb)
|
||||
{
|
||||
int demuxer_bytes = iSize;
|
||||
|
||||
uint8_t *demuxer_content = pData;
|
||||
|
||||
if (m_convert_bitstream)
|
||||
{
|
||||
// convert demuxer packet from bitstream to bytestream (AnnexB)
|
||||
int bytestream_size = 0;
|
||||
uint8_t *bytestream_buff = NULL;
|
||||
|
||||
BitstreamConvert(demuxer_content, demuxer_bytes, &bytestream_buff, &bytestream_size);
|
||||
if (bytestream_buff && (bytestream_size > 0))
|
||||
{
|
||||
m_convertSize = bytestream_size;
|
||||
m_convertBuffer = bytestream_buff;
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
m_inputBuffer = pData;
|
||||
m_inputSize = iSize;
|
||||
CLog::Log(LOGERROR, "CBitstreamConverter::Convert error converting. disable converter\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_inputBuffer = pData;
|
||||
m_inputSize = iSize;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_inputBuffer = pData;
|
||||
m_inputSize = iSize;
|
||||
|
||||
if (m_convert_bytestream)
|
||||
{
|
||||
if(m_convertBuffer)
|
||||
{
|
||||
m_dllAvUtil->av_free(m_convertBuffer);
|
||||
m_convertBuffer = NULL;
|
||||
}
|
||||
m_convertSize = 0;
|
||||
|
||||
// convert demuxer packet from bytestream (AnnexB) to bitstream
|
||||
ByteIOContext *pb;
|
||||
|
||||
if(m_dllAvFormat->url_open_dyn_buf(&pb) < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_convertSize = avc_parse_nal_units(pb, pData, iSize);
|
||||
m_convertSize = m_dllAvFormat->url_close_dyn_buf(pb, &m_convertBuffer);
|
||||
}
|
||||
else if (m_convert_3byteTo4byteNALSize)
|
||||
{
|
||||
if(m_convertBuffer)
|
||||
{
|
||||
m_dllAvUtil->av_free(m_convertBuffer);
|
||||
m_convertBuffer = NULL;
|
||||
}
|
||||
m_convertSize = 0;
|
||||
|
||||
// convert demuxer packet from 3 byte NAL sizes to 4 byte
|
||||
ByteIOContext *pb;
|
||||
if (m_dllAvFormat->url_open_dyn_buf(&pb) < 0)
|
||||
return false;
|
||||
|
||||
uint32_t nal_size;
|
||||
uint8_t *end = pData + iSize;
|
||||
uint8_t *nal_start = pData;
|
||||
while (nal_start < end)
|
||||
{
|
||||
nal_size = OMX_RB24(nal_start);
|
||||
m_dllAvFormat->put_be32(pb, nal_size);
|
||||
nal_start += 3;
|
||||
m_dllAvFormat->put_buffer(pb, nal_start, nal_size);
|
||||
nal_start += nal_size;
|
||||
}
|
||||
|
||||
m_convertSize = m_dllAvFormat->url_close_dyn_buf(pb, &m_convertBuffer);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (m_codec == CODEC_ID_VC1)
|
||||
{
|
||||
if(!(iSize >= 3 && !pData[0] && !pData[1] && pData[2] == 1) && !m_convert_vc1)
|
||||
m_convert_vc1 = true;
|
||||
|
||||
if(m_convert_vc1)
|
||||
{
|
||||
|
||||
m_inputBuffer = pData;
|
||||
m_inputSize = iSize;
|
||||
|
||||
if(m_convertBuffer)
|
||||
{
|
||||
m_dllAvUtil->av_free(m_convertBuffer);
|
||||
m_convertBuffer = NULL;
|
||||
}
|
||||
m_convertSize = 0;
|
||||
|
||||
ByteIOContext *pb;
|
||||
if (m_dllAvFormat->url_open_dyn_buf(&pb) < 0)
|
||||
return false;
|
||||
|
||||
m_dllAvFormat->put_byte(pb, 0);
|
||||
m_dllAvFormat->put_byte(pb, 0);
|
||||
m_dllAvFormat->put_byte(pb, !m_convert_vc1 ? 0 : 1);
|
||||
m_dllAvFormat->put_byte(pb, !m_convert_vc1 ? 0 : 0xd);
|
||||
m_dllAvFormat->put_buffer(pb, pData, iSize);
|
||||
m_convertSize = m_dllAvFormat->url_close_dyn_buf(pb, &m_convertBuffer);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_inputBuffer = pData;
|
||||
m_inputSize = iSize;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
uint8_t *CBitstreamConverter::GetConvertBuffer()
|
||||
{
|
||||
if((m_convert_bitstream || m_convert_bytestream || m_convert_3byteTo4byteNALSize || m_convert_vc1) && m_convertBuffer != NULL)
|
||||
return m_convertBuffer;
|
||||
else
|
||||
return m_inputBuffer;
|
||||
}
|
||||
|
||||
int CBitstreamConverter::GetConvertSize()
|
||||
{
|
||||
if((m_convert_bitstream || m_convert_bytestream || m_convert_3byteTo4byteNALSize || m_convert_vc1) && m_convertBuffer != NULL)
|
||||
return m_convertSize;
|
||||
else
|
||||
return m_inputSize;
|
||||
}
|
||||
|
||||
uint8_t *CBitstreamConverter::GetExtraData()
|
||||
{
|
||||
return m_extradata;
|
||||
}
|
||||
int CBitstreamConverter::GetExtraSize()
|
||||
{
|
||||
return m_extrasize;
|
||||
}
|
||||
|
||||
bool CBitstreamConverter::BitstreamConvertInit(void *in_extradata, int in_extrasize)
|
||||
{
|
||||
// based on h264_mp4toannexb_bsf.c (ffmpeg)
|
||||
// which is Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr>
|
||||
// and Licensed GPL 2.1 or greater
|
||||
|
||||
m_sps_pps_size = 0;
|
||||
m_sps_pps_context.sps_pps_data = NULL;
|
||||
|
||||
// nothing to filter
|
||||
if (!in_extradata || in_extrasize < 6)
|
||||
return false;
|
||||
|
||||
uint16_t unit_size;
|
||||
uint32_t total_size = 0;
|
||||
uint8_t *out = NULL, unit_nb, sps_done = 0;
|
||||
const uint8_t *extradata = (uint8_t*)in_extradata + 4;
|
||||
static const uint8_t nalu_header[4] = {0, 0, 0, 1};
|
||||
|
||||
// retrieve length coded size
|
||||
m_sps_pps_context.length_size = (*extradata++ & 0x3) + 1;
|
||||
if (m_sps_pps_context.length_size == 3)
|
||||
return false;
|
||||
|
||||
// retrieve sps and pps unit(s)
|
||||
unit_nb = *extradata++ & 0x1f; // number of sps unit(s)
|
||||
if (!unit_nb)
|
||||
{
|
||||
unit_nb = *extradata++; // number of pps unit(s)
|
||||
sps_done++;
|
||||
}
|
||||
while (unit_nb--)
|
||||
{
|
||||
unit_size = extradata[0] << 8 | extradata[1];
|
||||
total_size += unit_size + 4;
|
||||
if ( (extradata + 2 + unit_size) > ((uint8_t*)in_extradata + in_extrasize) )
|
||||
{
|
||||
free(out);
|
||||
return false;
|
||||
}
|
||||
out = (uint8_t*)realloc(out, total_size);
|
||||
if (!out)
|
||||
return false;
|
||||
|
||||
memcpy(out + total_size - unit_size - 4, nalu_header, 4);
|
||||
memcpy(out + total_size - unit_size, extradata + 2, unit_size);
|
||||
extradata += 2 + unit_size;
|
||||
|
||||
if (!unit_nb && !sps_done++)
|
||||
unit_nb = *extradata++; // number of pps unit(s)
|
||||
}
|
||||
|
||||
m_sps_pps_context.sps_pps_data = out;
|
||||
m_sps_pps_context.size = total_size;
|
||||
m_sps_pps_context.first_idr = 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBitstreamConverter::BitstreamConvert(uint8_t* pData, int iSize, uint8_t **poutbuf, int *poutbuf_size)
|
||||
{
|
||||
// based on h264_mp4toannexb_bsf.c (ffmpeg)
|
||||
// which is Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr>
|
||||
// and Licensed GPL 2.1 or greater
|
||||
|
||||
|
||||
uint8_t *buf = pData;
|
||||
uint32_t buf_size = iSize;
|
||||
uint8_t unit_type;
|
||||
int32_t nal_size;
|
||||
uint32_t cumul_size = 0;
|
||||
const uint8_t *buf_end = buf + buf_size;
|
||||
|
||||
do
|
||||
{
|
||||
if (buf + m_sps_pps_context.length_size > buf_end)
|
||||
goto fail;
|
||||
|
||||
if (m_sps_pps_context.length_size == 1)
|
||||
nal_size = buf[0];
|
||||
else if (m_sps_pps_context.length_size == 2)
|
||||
nal_size = buf[0] << 8 | buf[1];
|
||||
else
|
||||
nal_size = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
|
||||
|
||||
buf += m_sps_pps_context.length_size;
|
||||
unit_type = *buf & 0x1f;
|
||||
|
||||
if (buf + nal_size > buf_end || nal_size < 0)
|
||||
goto fail;
|
||||
|
||||
// prepend only to the first type 5 NAL unit of an IDR picture
|
||||
if (m_sps_pps_context.first_idr && unit_type == 5)
|
||||
{
|
||||
BitstreamAllocAndCopy(poutbuf, poutbuf_size,
|
||||
m_sps_pps_context.sps_pps_data, m_sps_pps_context.size, buf, nal_size);
|
||||
m_sps_pps_context.first_idr = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
BitstreamAllocAndCopy(poutbuf, poutbuf_size, NULL, 0, buf, nal_size);
|
||||
if (!m_sps_pps_context.first_idr && unit_type == 1)
|
||||
m_sps_pps_context.first_idr = 1;
|
||||
}
|
||||
|
||||
buf += nal_size;
|
||||
cumul_size += nal_size + m_sps_pps_context.length_size;
|
||||
} while (cumul_size < buf_size);
|
||||
|
||||
return true;
|
||||
|
||||
fail:
|
||||
free(*poutbuf);
|
||||
*poutbuf = NULL;
|
||||
*poutbuf_size = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
void CBitstreamConverter::BitstreamAllocAndCopy( uint8_t **poutbuf, int *poutbuf_size,
|
||||
const uint8_t *sps_pps, uint32_t sps_pps_size, const uint8_t *in, uint32_t in_size)
|
||||
{
|
||||
// based on h264_mp4toannexb_bsf.c (ffmpeg)
|
||||
// which is Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr>
|
||||
// and Licensed GPL 2.1 or greater
|
||||
|
||||
#define CHD_WB32(p, d) { \
|
||||
((uint8_t*)(p))[3] = (d); \
|
||||
((uint8_t*)(p))[2] = (d) >> 8; \
|
||||
((uint8_t*)(p))[1] = (d) >> 16; \
|
||||
((uint8_t*)(p))[0] = (d) >> 24; }
|
||||
|
||||
uint32_t offset = *poutbuf_size;
|
||||
uint8_t nal_header_size = offset ? 3 : 4;
|
||||
|
||||
*poutbuf_size += sps_pps_size + in_size + nal_header_size;
|
||||
*poutbuf = (uint8_t*)realloc(*poutbuf, *poutbuf_size);
|
||||
if (sps_pps)
|
||||
memcpy(*poutbuf + offset, sps_pps, sps_pps_size);
|
||||
|
||||
memcpy(*poutbuf + sps_pps_size + nal_header_size + offset, in, in_size);
|
||||
if (!offset)
|
||||
{
|
||||
CHD_WB32(*poutbuf + sps_pps_size, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*poutbuf + offset + sps_pps_size)[0] = 0;
|
||||
(*poutbuf + offset + sps_pps_size)[1] = 0;
|
||||
(*poutbuf + offset + sps_pps_size)[2] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
172
BitstreamConverter.h
Normal file
172
BitstreamConverter.h
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* Copyright (C) 2010 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _BITSTREAMCONVERTER_H_
|
||||
#define _BITSTREAMCONVERTER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "DllAvUtil.h"
|
||||
#include "DllAvFormat.h"
|
||||
#include "DllAvFilter.h"
|
||||
#include "DllAvCodec.h"
|
||||
#include "DllAvCore.h"
|
||||
|
||||
typedef struct {
|
||||
uint8_t *buffer, *start;
|
||||
int offbits, length, oflow;
|
||||
} bits_reader_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TODO: refactor this so as not to need these ffmpeg routines.
|
||||
// These are not exposed in ffmpeg's API so we dupe them here.
|
||||
// AVC helper functions for muxers,
|
||||
// * Copyright (c) 2006 Baptiste Coudurier <baptiste.coudurier@smartjog.com>
|
||||
// This is part of FFmpeg
|
||||
// * License as published by the Free Software Foundation; either
|
||||
// * version 2.1 of the License, or (at your option) any later version.
|
||||
#define OMX_RB16(x) \
|
||||
((((const uint8_t*)(x))[0] << 8) | \
|
||||
((const uint8_t*)(x)) [1])
|
||||
|
||||
#define OMX_RB24(x) \
|
||||
((((const uint8_t*)(x))[0] << 16) | \
|
||||
(((const uint8_t*)(x))[1] << 8) | \
|
||||
((const uint8_t*)(x))[2])
|
||||
|
||||
#define OMX_RB32(x) \
|
||||
((((const uint8_t*)(x))[0] << 24) | \
|
||||
(((const uint8_t*)(x))[1] << 16) | \
|
||||
(((const uint8_t*)(x))[2] << 8) | \
|
||||
((const uint8_t*)(x))[3])
|
||||
|
||||
#define OMX_WB32(p, d) { \
|
||||
((uint8_t*)(p))[3] = (d); \
|
||||
((uint8_t*)(p))[2] = (d) >> 8; \
|
||||
((uint8_t*)(p))[1] = (d) >> 16; \
|
||||
((uint8_t*)(p))[0] = (d) >> 24; }
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const uint8_t *data;
|
||||
const uint8_t *end;
|
||||
int head;
|
||||
uint64_t cache;
|
||||
} nal_bitstream;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int profile_idc;
|
||||
int level_idc;
|
||||
int sps_id;
|
||||
|
||||
int chroma_format_idc;
|
||||
int separate_colour_plane_flag;
|
||||
int bit_depth_luma_minus8;
|
||||
int bit_depth_chroma_minus8;
|
||||
int qpprime_y_zero_transform_bypass_flag;
|
||||
int seq_scaling_matrix_present_flag;
|
||||
|
||||
int log2_max_frame_num_minus4;
|
||||
int pic_order_cnt_type;
|
||||
int log2_max_pic_order_cnt_lsb_minus4;
|
||||
|
||||
int max_num_ref_frames;
|
||||
int gaps_in_frame_num_value_allowed_flag;
|
||||
int pic_width_in_mbs_minus1;
|
||||
int pic_height_in_map_units_minus1;
|
||||
|
||||
int frame_mbs_only_flag;
|
||||
int mb_adaptive_frame_field_flag;
|
||||
|
||||
int direct_8x8_inference_flag;
|
||||
|
||||
int frame_cropping_flag;
|
||||
int frame_crop_left_offset;
|
||||
int frame_crop_right_offset;
|
||||
int frame_crop_top_offset;
|
||||
int frame_crop_bottom_offset;
|
||||
} sps_info_struct;
|
||||
|
||||
class CBitstreamConverter
|
||||
{
|
||||
public:
|
||||
CBitstreamConverter();
|
||||
~CBitstreamConverter();
|
||||
// Required overrides
|
||||
static void bits_reader_set( bits_reader_t *br, uint8_t *buf, int len );
|
||||
static uint32_t read_bits( bits_reader_t *br, int nbits );
|
||||
static void skip_bits( bits_reader_t *br, int nbits );
|
||||
static uint32_t get_bits( bits_reader_t *br, int nbits );
|
||||
|
||||
bool Open(enum CodecID codec, uint8_t *in_extradata, int in_extrasize, bool to_annexb);
|
||||
void Close(void);
|
||||
bool NeedConvert(void) { return m_convert_bitstream; };
|
||||
bool Convert(uint8_t *pData, int iSize);
|
||||
uint8_t *GetConvertBuffer(void);
|
||||
int GetConvertSize();
|
||||
uint8_t *GetExtraData(void);
|
||||
int GetExtraSize();
|
||||
void parseh264_sps(uint8_t *sps, uint32_t sps_size, bool *interlaced, int32_t *max_ref_frames);
|
||||
protected:
|
||||
// bytestream (Annex B) to bistream conversion support.
|
||||
void nal_bs_init(nal_bitstream *bs, const uint8_t *data, size_t size);
|
||||
uint32_t nal_bs_read(nal_bitstream *bs, int n);
|
||||
bool nal_bs_eos(nal_bitstream *bs);
|
||||
int nal_bs_read_ue(nal_bitstream *bs);
|
||||
const uint8_t *avc_find_startcode_internal(const uint8_t *p, const uint8_t *end);
|
||||
const uint8_t *avc_find_startcode(const uint8_t *p, const uint8_t *end);
|
||||
const int avc_parse_nal_units(ByteIOContext *pb, const uint8_t *buf_in, int size);
|
||||
const int avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size);
|
||||
const int isom_write_avcc(ByteIOContext *pb, const uint8_t *data, int len);
|
||||
// bitstream to bytestream (Annex B) conversion support.
|
||||
bool BitstreamConvertInit(void *in_extradata, int in_extrasize);
|
||||
bool BitstreamConvert(uint8_t* pData, int iSize, uint8_t **poutbuf, int *poutbuf_size);
|
||||
void BitstreamAllocAndCopy( uint8_t **poutbuf, int *poutbuf_size,
|
||||
const uint8_t *sps_pps, uint32_t sps_pps_size, const uint8_t *in, uint32_t in_size);
|
||||
|
||||
typedef struct omx_bitstream_ctx {
|
||||
uint8_t length_size;
|
||||
uint8_t first_idr;
|
||||
uint8_t *sps_pps_data;
|
||||
uint32_t size;
|
||||
} omx_bitstream_ctx;
|
||||
|
||||
uint8_t *m_convertBuffer;
|
||||
int m_convertSize;
|
||||
uint8_t *m_inputBuffer;
|
||||
int m_inputSize;
|
||||
|
||||
uint32_t m_sps_pps_size;
|
||||
omx_bitstream_ctx m_sps_pps_context;
|
||||
bool m_convert_bitstream;
|
||||
bool m_to_annexb;
|
||||
bool m_convert_vc1;
|
||||
|
||||
uint8_t *m_extradata;
|
||||
int m_extrasize;
|
||||
bool m_convert_3byteTo4byteNALSize;
|
||||
bool m_convert_bytestream;
|
||||
DllAvUtil *m_dllAvUtil;
|
||||
DllAvFormat *m_dllAvFormat;
|
||||
CodecID m_codec;
|
||||
};
|
||||
|
||||
#endif
|
||||
340
COPYING
Normal file
340
COPYING
Normal file
|
|
@ -0,0 +1,340 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
377
DllAvCodec.h
Normal file
377
DllAvCodec.h
Normal file
|
|
@ -0,0 +1,377 @@
|
|||
#pragma once
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#if (defined HAVE_CONFIG_H) && (!defined WIN32)
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include "DynamicDll.h"
|
||||
#include "DllAvCore.h"
|
||||
#include "utils/log.h"
|
||||
|
||||
#ifndef AV_NOWARN_DEPRECATED
|
||||
#define AV_NOWARN_DEPRECATED
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#ifndef HAVE_MMX
|
||||
#define HAVE_MMX
|
||||
#endif
|
||||
#ifndef __STDC_CONSTANT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
#ifndef __STDC_LIMIT_MACROS
|
||||
#define __STDC_LIMIT_MACROS
|
||||
#endif
|
||||
|
||||
#ifndef __GNUC__
|
||||
#pragma warning(disable:4244)
|
||||
#endif
|
||||
|
||||
#if (defined USE_EXTERNAL_FFMPEG)
|
||||
#if (defined HAVE_LIBAVCODEC_AVCODEC_H)
|
||||
#include <libavcodec/avcodec.h>
|
||||
#if (defined HAVE_LIBAVCODEC_OPT_H)
|
||||
#include <libavcodec/opt.h>
|
||||
#endif
|
||||
#if (defined AVPACKET_IN_AVFORMAT)
|
||||
#include <libavformat/avformat.h>
|
||||
#endif
|
||||
#elif (defined HAVE_FFMPEG_AVCODEC_H)
|
||||
#include <ffmpeg/avcodec.h>
|
||||
#include <ffmpeg/opt.h>
|
||||
#if (defined AVPACKET_IN_AVFORMAT)
|
||||
#include <ffmpeg/avformat.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* From non-public audioconvert.h */
|
||||
int64_t avcodec_guess_channel_layout(int nb_channels, enum CodecID codec_id, const char *fmt_name);
|
||||
struct AVAudioConvert;
|
||||
typedef struct AVAudioConvert AVAudioConvert;
|
||||
AVAudioConvert *av_audio_convert_alloc(enum AVSampleFormat out_fmt, int out_channels,
|
||||
enum AVSampleFormat in_fmt, int in_channels,
|
||||
const float *matrix, int flags);
|
||||
void av_audio_convert_free(AVAudioConvert *ctx);
|
||||
int av_audio_convert(AVAudioConvert *ctx,
|
||||
void * const out[6], const int out_stride[6],
|
||||
const void * const in[6], const int in_stride[6], int len);
|
||||
#else
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "libavcodec/audioconvert.h"
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Some convenience macros introduced at this particular revision of libavcodec.
|
||||
*/
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(52,25,0)
|
||||
#define CH_LAYOUT_5POINT0_BACK (CH_LAYOUT_SURROUND|CH_BACK_LEFT|CH_BACK_RIGHT)
|
||||
#define CH_LAYOUT_5POINT1_BACK (CH_LAYOUT_5POINT0_BACK|CH_LOW_FREQUENCY)
|
||||
#undef CH_LAYOUT_7POINT1_WIDE
|
||||
#define CH_LAYOUT_7POINT1_WIDE (CH_LAYOUT_5POINT1_BACK|\
|
||||
CH_FRONT_LEFT_OF_CENTER|CH_FRONT_RIGHT_OF_CENTER)
|
||||
#endif
|
||||
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(52,64,0)
|
||||
// API added on: 2010-03-31
|
||||
#define AVMediaType CodecType
|
||||
#define AVMEDIA_TYPE_UNKNOWN CODEC_TYPE_UNKNOWN
|
||||
#define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO
|
||||
#define AVMEDIA_TYPE_AUDIO CODEC_TYPE_AUDIO
|
||||
#define AVMEDIA_TYPE_DATA CODEC_TYPE_DATA
|
||||
#define AVMEDIA_TYPE_SUBTITLE CODEC_TYPE_SUBTITLE
|
||||
#define AVMEDIA_TYPE_ATTACHMENT CODEC_TYPE_ATTACHMENT
|
||||
#define AVMEDIA_TYPE_NB CODEC_TYPE_NB
|
||||
#endif
|
||||
|
||||
//#include "threads/SingleLock.h"
|
||||
|
||||
class DllAvCodecInterface
|
||||
{
|
||||
public:
|
||||
virtual ~DllAvCodecInterface() {}
|
||||
virtual void avcodec_register_all(void)=0;
|
||||
virtual void avcodec_flush_buffers(AVCodecContext *avctx)=0;
|
||||
virtual int avcodec_open_dont_call(AVCodecContext *avctx, AVCodec *codec)=0;
|
||||
virtual AVCodec *avcodec_find_decoder(enum CodecID id)=0;
|
||||
virtual AVCodec *avcodec_find_encoder(enum CodecID id)=0;
|
||||
virtual int avcodec_close_dont_call(AVCodecContext *avctx)=0;
|
||||
virtual AVFrame *avcodec_alloc_frame(void)=0;
|
||||
virtual int avpicture_fill(AVPicture *picture, uint8_t *ptr, PixelFormat pix_fmt, int width, int height)=0;
|
||||
virtual int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, AVPacket *avpkt)=0;
|
||||
virtual int avcodec_decode_audio3(AVCodecContext *avctx, int16_t *samples, int *frame_size_ptr, AVPacket *avpkt)=0;
|
||||
virtual int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, int *got_sub_ptr, AVPacket *avpkt)=0;
|
||||
virtual int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size, const short *samples)=0;
|
||||
virtual int avpicture_get_size(PixelFormat pix_fmt, int width, int height)=0;
|
||||
virtual AVCodecContext *avcodec_alloc_context(void)=0;
|
||||
virtual void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)=0;
|
||||
virtual void avcodec_get_context_defaults(AVCodecContext *s)=0;
|
||||
virtual AVCodecParserContext *av_parser_init(int codec_id)=0;
|
||||
virtual int av_parser_parse2(AVCodecParserContext *s,AVCodecContext *avctx, uint8_t **poutbuf, int *poutbuf_size,
|
||||
const uint8_t *buf, int buf_size,
|
||||
int64_t pts, int64_t dts, int64_t pos)=0;
|
||||
virtual void av_parser_close(AVCodecParserContext *s)=0;
|
||||
virtual AVBitStreamFilterContext *av_bitstream_filter_init(const char *name)=0;
|
||||
virtual int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc,
|
||||
AVCodecContext *avctx, const char *args,
|
||||
uint8_t **poutbuf, int *poutbuf_size,
|
||||
const uint8_t *buf, int buf_size, int keyframe) =0;
|
||||
virtual void av_bitstream_filter_close(AVBitStreamFilterContext *bsfc) =0;
|
||||
virtual void avpicture_free(AVPicture *picture)=0;
|
||||
virtual void av_free_packet(AVPacket *pkt)=0;
|
||||
virtual int avpicture_alloc(AVPicture *picture, PixelFormat pix_fmt, int width, int height)=0;
|
||||
virtual enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum PixelFormat *fmt)=0;
|
||||
virtual int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic)=0;
|
||||
virtual void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic)=0;
|
||||
virtual int avcodec_thread_init(AVCodecContext *s, int thread_count)=0;
|
||||
virtual AVCodec *av_codec_next(AVCodec *c)=0;
|
||||
virtual AVAudioConvert *av_audio_convert_alloc(enum AVSampleFormat out_fmt, int out_channels,
|
||||
enum AVSampleFormat in_fmt , int in_channels,
|
||||
const float *matrix , int flags)=0;
|
||||
virtual void av_audio_convert_free(AVAudioConvert *ctx)=0;
|
||||
virtual int av_audio_convert(AVAudioConvert *ctx,
|
||||
void * const out[6], const int out_stride[6],
|
||||
const void * const in[6], const int in_stride[6], int len)=0;
|
||||
virtual int av_dup_packet(AVPacket *pkt)=0;
|
||||
virtual void av_init_packet(AVPacket *pkt)=0;
|
||||
virtual int64_t avcodec_guess_channel_layout(int nb_channels, enum CodecID codec_id, const char *fmt_name)=0;
|
||||
};
|
||||
|
||||
#if (defined USE_EXTERNAL_FFMPEG)
|
||||
|
||||
// Use direct layer
|
||||
class DllAvCodec : public DllDynamic, DllAvCodecInterface
|
||||
{
|
||||
public:
|
||||
virtual ~DllAvCodec() {}
|
||||
virtual void avcodec_register_all()
|
||||
{
|
||||
::avcodec_register_all();
|
||||
}
|
||||
virtual void avcodec_flush_buffers(AVCodecContext *avctx) { ::avcodec_flush_buffers(avctx); }
|
||||
virtual int avcodec_open(AVCodecContext *avctx, AVCodec *codec)
|
||||
{
|
||||
return ::avcodec_open(avctx, codec);
|
||||
}
|
||||
virtual int avcodec_open_dont_call(AVCodecContext *avctx, AVCodec *codec) { *(int *)0x0 = 0; return 0; }
|
||||
virtual int avcodec_close_dont_call(AVCodecContext *avctx) { *(int *)0x0 = 0; return 0; }
|
||||
virtual AVCodec *avcodec_find_decoder(enum CodecID id) { return ::avcodec_find_decoder(id); }
|
||||
virtual AVCodec *avcodec_find_encoder(enum CodecID id) { return ::avcodec_find_encoder(id); }
|
||||
virtual int avcodec_close(AVCodecContext *avctx)
|
||||
{
|
||||
return ::avcodec_close(avctx);
|
||||
}
|
||||
virtual AVFrame *avcodec_alloc_frame() { return ::avcodec_alloc_frame(); }
|
||||
virtual int avpicture_fill(AVPicture *picture, uint8_t *ptr, PixelFormat pix_fmt, int width, int height) { return ::avpicture_fill(picture, ptr, pix_fmt, width, height); }
|
||||
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52,23,0)
|
||||
// API added on: 2009-04-07
|
||||
virtual int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, AVPacket *avpkt) { return ::avcodec_decode_video2(avctx, picture, got_picture_ptr, avpkt); }
|
||||
virtual int avcodec_decode_audio3(AVCodecContext *avctx, int16_t *samples, int *frame_size_ptr, AVPacket *avpkt) { return ::avcodec_decode_audio3(avctx, samples, frame_size_ptr, avpkt); }
|
||||
virtual int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, int *got_sub_ptr, AVPacket *avpkt) { return ::avcodec_decode_subtitle2(avctx, sub, got_sub_ptr, avpkt); }
|
||||
#else
|
||||
virtual int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, AVPacket *avpkt) { return ::avcodec_decode_video(avctx, picture, got_picture_ptr, avpkt->data, avpkt->size); }
|
||||
virtual int avcodec_decode_audio3(AVCodecContext *avctx, int16_t *samples, int *frame_size_ptr, AVPacket *avpkt) { return ::avcodec_decode_audio2(avctx, samples, frame_size_ptr, avpkt->data, avpkt->size); }
|
||||
virtual int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, int *got_sub_ptr, AVPacket *avpkt) { return ::avcodec_decode_subtitle(avctx, sub, got_sub_ptr, avpkt->data, avpkt->size); }
|
||||
#endif
|
||||
virtual int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size, const short *samples) { return ::avcodec_encode_audio(avctx, buf, buf_size, samples); }
|
||||
virtual int avpicture_get_size(PixelFormat pix_fmt, int width, int height) { return ::avpicture_get_size(pix_fmt, width, height); }
|
||||
virtual AVCodecContext *avcodec_alloc_context() { return ::avcodec_alloc_context(); }
|
||||
virtual void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) { ::avcodec_string(buf, buf_size, enc, encode); }
|
||||
virtual void avcodec_get_context_defaults(AVCodecContext *s) { ::avcodec_get_context_defaults(s); }
|
||||
|
||||
virtual AVCodecParserContext *av_parser_init(int codec_id) { return ::av_parser_init(codec_id); }
|
||||
virtual int av_parser_parse2(AVCodecParserContext *s,AVCodecContext *avctx, uint8_t **poutbuf, int *poutbuf_size,
|
||||
const uint8_t *buf, int buf_size,
|
||||
int64_t pts, int64_t dts, int64_t pos)
|
||||
{
|
||||
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52,21,0)
|
||||
// API added on : 2009-03-05
|
||||
return ::av_parser_parse2(s, avctx, poutbuf, poutbuf_size, buf, buf_size, pts, dts, pos);
|
||||
#else
|
||||
return ::av_parser_parse(s, avctx, poutbuf, poutbuf_size, buf, buf_size, pts, dts);
|
||||
#endif
|
||||
}
|
||||
virtual void av_parser_close(AVCodecParserContext *s) { ::av_parser_close(s); }
|
||||
|
||||
virtual AVBitStreamFilterContext *av_bitstream_filter_init(const char *name) { return ::av_bitstream_filter_init(name); }
|
||||
virtual int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc,
|
||||
AVCodecContext *avctx, const char *args,
|
||||
uint8_t **poutbuf, int *poutbuf_size,
|
||||
const uint8_t *buf, int buf_size, int keyframe) { return ::av_bitstream_filter_filter(bsfc, avctx, args, poutbuf, poutbuf_size, buf, buf_size, keyframe); }
|
||||
virtual void av_bitstream_filter_close(AVBitStreamFilterContext *bsfc) { ::av_bitstream_filter_close(bsfc); }
|
||||
|
||||
virtual void avpicture_free(AVPicture *picture) { ::avpicture_free(picture); }
|
||||
virtual void av_free_packet(AVPacket *pkt) { ::av_free_packet(pkt); }
|
||||
virtual int avpicture_alloc(AVPicture *picture, PixelFormat pix_fmt, int width, int height) { return ::avpicture_alloc(picture, pix_fmt, width, height); }
|
||||
virtual int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic) { return ::avcodec_default_get_buffer(s, pic); }
|
||||
virtual void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic) { ::avcodec_default_release_buffer(s, pic); }
|
||||
virtual enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum PixelFormat *fmt) { return ::avcodec_default_get_format(s, fmt); }
|
||||
virtual int avcodec_thread_init(AVCodecContext *s, int thread_count) { return ::avcodec_thread_init(s, thread_count); }
|
||||
virtual AVCodec *av_codec_next(AVCodec *c) { return ::av_codec_next(c); }
|
||||
virtual AVAudioConvert *av_audio_convert_alloc(enum AVSampleFormat out_fmt, int out_channels,
|
||||
enum AVSampleFormat in_fmt , int in_channels,
|
||||
const float *matrix , int flags)
|
||||
{ return ::av_audio_convert_alloc(out_fmt, out_channels, in_fmt, in_channels, matrix, flags); }
|
||||
virtual void av_audio_convert_free(AVAudioConvert *ctx)
|
||||
{ ::av_audio_convert_free(ctx); }
|
||||
|
||||
virtual int av_audio_convert(AVAudioConvert *ctx,
|
||||
void * const out[6], const int out_stride[6],
|
||||
const void * const in[6], const int in_stride[6], int len)
|
||||
{ return ::av_audio_convert(ctx, out, out_stride, in, in_stride, len); }
|
||||
|
||||
virtual int av_dup_packet(AVPacket *pkt) { return ::av_dup_packet(pkt); }
|
||||
virtual void av_init_packet(AVPacket *pkt) { return ::av_init_packet(pkt); }
|
||||
virtual int64_t avcodec_guess_channel_layout(int nb_channels, enum CodecID codec_id, const char *fmt_name) { return ::avcodec_guess_channel_layout(nb_channels, codec_id, fmt_name); }
|
||||
|
||||
// DLL faking.
|
||||
virtual bool ResolveExports() { return true; }
|
||||
virtual bool Load() {
|
||||
CLog::Log(LOGDEBUG, "DllAvCodec: Using libavcodec system library");
|
||||
return true;
|
||||
}
|
||||
virtual void Unload() {}
|
||||
};
|
||||
#else
|
||||
class DllAvCodec : public DllDynamic, DllAvCodecInterface
|
||||
{
|
||||
DECLARE_DLL_WRAPPER(DllAvCodec, DLL_PATH_LIBAVCODEC)
|
||||
#ifndef _LINUX
|
||||
DEFINE_FUNC_ALIGNED1(void, __cdecl, avcodec_flush_buffers, AVCodecContext*)
|
||||
DEFINE_FUNC_ALIGNED2(int, __cdecl, avcodec_open_dont_call, AVCodecContext*, AVCodec *)
|
||||
DEFINE_FUNC_ALIGNED4(int, __cdecl, avcodec_decode_video2, AVCodecContext*, AVFrame*, int*, AVPacket*)
|
||||
DEFINE_FUNC_ALIGNED4(int, __cdecl, avcodec_decode_audio3, AVCodecContext*, int16_t*, int*, AVPacket*)
|
||||
DEFINE_FUNC_ALIGNED4(int, __cdecl, avcodec_decode_subtitle2, AVCodecContext*, AVSubtitle*, int*, AVPacket*)
|
||||
DEFINE_FUNC_ALIGNED4(int, __cdecl, avcodec_encode_audio, AVCodecContext*, uint8_t*, int, const short*)
|
||||
DEFINE_FUNC_ALIGNED0(AVCodecContext*, __cdecl, avcodec_alloc_context)
|
||||
DEFINE_FUNC_ALIGNED1(AVCodecParserContext*, __cdecl, av_parser_init, int)
|
||||
DEFINE_FUNC_ALIGNED9(int, __cdecl, av_parser_parse2, AVCodecParserContext*,AVCodecContext*, uint8_t**, int*, const uint8_t*, int, int64_t, int64_t, int64_t)
|
||||
#else
|
||||
DEFINE_METHOD1(void, avcodec_flush_buffers, (AVCodecContext* p1))
|
||||
DEFINE_METHOD2(int, avcodec_open_dont_call, (AVCodecContext* p1, AVCodec *p2))
|
||||
DEFINE_METHOD4(int, avcodec_decode_video2, (AVCodecContext* p1, AVFrame *p2, int *p3, AVPacket *p4))
|
||||
DEFINE_METHOD4(int, avcodec_decode_audio3, (AVCodecContext* p1, int16_t *p2, int *p3, AVPacket *p4))
|
||||
DEFINE_METHOD4(int, avcodec_decode_subtitle2, (AVCodecContext* p1, AVSubtitle *p2, int *p3, AVPacket *p4))
|
||||
DEFINE_METHOD4(int, avcodec_encode_audio, (AVCodecContext* p1, uint8_t *p2, int p3, const short *p4))
|
||||
DEFINE_METHOD0(AVCodecContext*, avcodec_alloc_context)
|
||||
DEFINE_METHOD1(AVCodecParserContext*, av_parser_init, (int p1))
|
||||
DEFINE_METHOD9(int, av_parser_parse2, (AVCodecParserContext* p1, AVCodecContext* p2, uint8_t** p3, int* p4, const uint8_t* p5, int p6, int64_t p7, int64_t p8, int64_t p9))
|
||||
#endif
|
||||
DEFINE_METHOD1(int, av_dup_packet, (AVPacket *p1))
|
||||
DEFINE_METHOD1(void, av_init_packet, (AVPacket *p1))
|
||||
DEFINE_METHOD3(int64_t, avcodec_guess_channel_layout, (int p1, enum CodecID p2, const char *p3))
|
||||
|
||||
LOAD_SYMBOLS();
|
||||
|
||||
DEFINE_METHOD0(void, avcodec_register_all_dont_call)
|
||||
DEFINE_METHOD1(AVCodec*, avcodec_find_decoder, (enum CodecID p1))
|
||||
DEFINE_METHOD1(AVCodec*, avcodec_find_encoder, (enum CodecID p1))
|
||||
DEFINE_METHOD1(int, avcodec_close_dont_call, (AVCodecContext *p1))
|
||||
DEFINE_METHOD0(AVFrame*, avcodec_alloc_frame)
|
||||
DEFINE_METHOD5(int, avpicture_fill, (AVPicture *p1, uint8_t *p2, PixelFormat p3, int p4, int p5))
|
||||
DEFINE_METHOD3(int, avpicture_get_size, (PixelFormat p1, int p2, int p3))
|
||||
DEFINE_METHOD4(void, avcodec_string, (char *p1, int p2, AVCodecContext *p3, int p4))
|
||||
DEFINE_METHOD1(void, avcodec_get_context_defaults, (AVCodecContext *p1))
|
||||
DEFINE_METHOD1(void, av_parser_close, (AVCodecParserContext *p1))
|
||||
DEFINE_METHOD1(void, avpicture_free, (AVPicture *p1))
|
||||
DEFINE_METHOD1(AVBitStreamFilterContext*, av_bitstream_filter_init, (const char *p1))
|
||||
DEFINE_METHOD8(int, av_bitstream_filter_filter, (AVBitStreamFilterContext* p1, AVCodecContext* p2, const char* p3, uint8_t** p4, int* p5, const uint8_t* p6, int p7, int p8))
|
||||
DEFINE_METHOD1(void, av_bitstream_filter_close, (AVBitStreamFilterContext *p1))
|
||||
DEFINE_METHOD1(void, av_free_packet, (AVPacket *p1))
|
||||
DEFINE_METHOD4(int, avpicture_alloc, (AVPicture *p1, PixelFormat p2, int p3, int p4))
|
||||
DEFINE_METHOD2(int, avcodec_default_get_buffer, (AVCodecContext *p1, AVFrame *p2))
|
||||
DEFINE_METHOD2(void, avcodec_default_release_buffer, (AVCodecContext *p1, AVFrame *p2))
|
||||
DEFINE_METHOD2(enum PixelFormat, avcodec_default_get_format, (struct AVCodecContext *p1, const enum PixelFormat *p2))
|
||||
|
||||
DEFINE_METHOD2(int, avcodec_thread_init, (AVCodecContext *p1, int p2))
|
||||
DEFINE_METHOD1(AVCodec*, av_codec_next, (AVCodec *p1))
|
||||
DEFINE_METHOD6(AVAudioConvert*, av_audio_convert_alloc, (enum AVSampleFormat p1, int p2,
|
||||
enum AVSampleFormat p3, int p4,
|
||||
const float *p5, int p6))
|
||||
DEFINE_METHOD1(void, av_audio_convert_free, (AVAudioConvert *p1));
|
||||
DEFINE_METHOD6(int, av_audio_convert, (AVAudioConvert *p1,
|
||||
void * const p2[6], const int p3[6],
|
||||
const void * const p4[6], const int p5[6], int p6))
|
||||
BEGIN_METHOD_RESOLVE()
|
||||
RESOLVE_METHOD(avcodec_flush_buffers)
|
||||
RESOLVE_METHOD_RENAME(avcodec_open,avcodec_open_dont_call)
|
||||
RESOLVE_METHOD_RENAME(avcodec_close,avcodec_close_dont_call)
|
||||
RESOLVE_METHOD(avcodec_find_decoder)
|
||||
RESOLVE_METHOD(avcodec_find_encoder)
|
||||
RESOLVE_METHOD(avcodec_alloc_frame)
|
||||
RESOLVE_METHOD_RENAME(avcodec_register_all, avcodec_register_all_dont_call)
|
||||
RESOLVE_METHOD(avpicture_fill)
|
||||
RESOLVE_METHOD(avcodec_decode_video2)
|
||||
RESOLVE_METHOD(avcodec_decode_audio3)
|
||||
RESOLVE_METHOD(avcodec_decode_subtitle2)
|
||||
RESOLVE_METHOD(avcodec_encode_audio)
|
||||
RESOLVE_METHOD(avpicture_get_size)
|
||||
RESOLVE_METHOD(avcodec_alloc_context)
|
||||
RESOLVE_METHOD(avcodec_string)
|
||||
RESOLVE_METHOD(avcodec_get_context_defaults)
|
||||
RESOLVE_METHOD(av_parser_init)
|
||||
RESOLVE_METHOD(av_parser_parse2)
|
||||
RESOLVE_METHOD(av_parser_close)
|
||||
RESOLVE_METHOD(av_bitstream_filter_init)
|
||||
RESOLVE_METHOD(av_bitstream_filter_filter)
|
||||
RESOLVE_METHOD(av_bitstream_filter_close)
|
||||
RESOLVE_METHOD(avpicture_free)
|
||||
RESOLVE_METHOD(avpicture_alloc)
|
||||
RESOLVE_METHOD(av_free_packet)
|
||||
RESOLVE_METHOD(avcodec_default_get_buffer)
|
||||
RESOLVE_METHOD(avcodec_default_release_buffer)
|
||||
RESOLVE_METHOD(avcodec_default_get_format)
|
||||
RESOLVE_METHOD(avcodec_thread_init)
|
||||
RESOLVE_METHOD(av_codec_next)
|
||||
RESOLVE_METHOD(av_audio_convert_alloc)
|
||||
RESOLVE_METHOD(av_audio_convert_free)
|
||||
RESOLVE_METHOD(av_audio_convert)
|
||||
RESOLVE_METHOD(av_dup_packet)
|
||||
RESOLVE_METHOD(av_init_packet)
|
||||
RESOLVE_METHOD(avcodec_guess_channel_layout)
|
||||
END_METHOD_RESOLVE()
|
||||
|
||||
/* dependencies of libavcodec */
|
||||
DllAvCore m_dllAvCore;
|
||||
// DllAvUtil loaded implicitely by m_dllAvCore
|
||||
|
||||
public:
|
||||
int avcodec_open(AVCodecContext *avctx, AVCodec *codec)
|
||||
{
|
||||
return avcodec_open_dont_call(avctx,codec);
|
||||
}
|
||||
int avcodec_close(AVCodecContext *avctx)
|
||||
{
|
||||
return avcodec_close_dont_call(avctx);
|
||||
}
|
||||
void avcodec_register_all()
|
||||
{
|
||||
avcodec_register_all_dont_call();
|
||||
}
|
||||
virtual bool Load()
|
||||
{
|
||||
if (!m_dllAvCore.Load())
|
||||
return false;
|
||||
return DllDynamic::Load();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
186
DllAvCore.h
Normal file
186
DllAvCore.h
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
#pragma once
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#if (defined HAVE_CONFIG_H) && (!defined WIN32)
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include "DynamicDll.h"
|
||||
#include "DllAvUtil.h"
|
||||
#include "utils/log.h"
|
||||
|
||||
#ifndef AV_NOWARN_DEPRECATED
|
||||
#define AV_NOWARN_DEPRECATED
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#ifdef USE_EXTERNAL_FFMPEG
|
||||
#ifdef HAVE_LIBAVUTIL_SAMPLEFMT_H
|
||||
// libavcore was merged to libavutil on 2010-02-15
|
||||
#include <libavutil/audioconvert.h>
|
||||
#include <libavutil/samplefmt.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBAVCORE_AVCORE_H
|
||||
#include <libavcore/avcore.h>
|
||||
#endif
|
||||
#ifdef HAVE_LIBAVCORE_SAMPLEFMT_H
|
||||
#include <libavcore/samplefmt.h>
|
||||
#endif
|
||||
|
||||
/* Needed for old FFmpeg versions as used below */
|
||||
#ifdef HAVE_LIBAVCODEC_AVCODEC_H
|
||||
#include <libavcodec/avcodec.h>
|
||||
#else
|
||||
#include <ffmpeg/avcodec.h>
|
||||
#endif
|
||||
#else
|
||||
#include "libavcore/avcore.h"
|
||||
#include "libavcore/samplefmt.h"
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Compatibility for old external FFmpeg versions. */
|
||||
|
||||
#ifdef USE_EXTERNAL_FFMPEG
|
||||
|
||||
#ifndef LIBAVCORE_VERSION_INT
|
||||
// API added on: 2010-07-21, removed on 2010-02-15
|
||||
#define LIBAVCORE_VERSION_INT 0
|
||||
#endif
|
||||
|
||||
#ifndef AV_SAMPLE_FMT_NONE
|
||||
// API added on: 2010-11-02
|
||||
#define AVSampleFormat SampleFormat
|
||||
#define AV_SAMPLE_FMT_NONE SAMPLE_FMT_NONE
|
||||
#define AV_SAMPLE_FMT_U8 SAMPLE_FMT_U8
|
||||
#define AV_SAMPLE_FMT_S16 SAMPLE_FMT_S16
|
||||
#define AV_SAMPLE_FMT_S32 SAMPLE_FMT_S32
|
||||
#define AV_SAMPLE_FMT_FLT SAMPLE_FMT_FLT
|
||||
#define AV_SAMPLE_FMT_DBL SAMPLE_FMT_DBL
|
||||
#endif
|
||||
|
||||
#ifndef AV_CH_FRONT_LEFT
|
||||
// API added on: 2010-11-21
|
||||
#define AV_CH_FRONT_LEFT CH_FRONT_LEFT
|
||||
#define AV_CH_FRONT_RIGHT CH_FRONT_RIGHT
|
||||
#define AV_CH_FRONT_CENTER CH_FRONT_CENTER
|
||||
#define AV_CH_LOW_FREQUENCY CH_LOW_FREQUENCY
|
||||
#define AV_CH_BACK_LEFT CH_BACK_LEFT
|
||||
#define AV_CH_BACK_RIGHT CH_BACK_RIGHT
|
||||
#define AV_CH_FRONT_LEFT_OF_CENTER CH_FRONT_LEFT_OF_CENTER
|
||||
#define AV_CH_FRONT_RIGHT_OF_CENTER CH_FRONT_RIGHT_OF_CENTER
|
||||
#define AV_CH_BACK_CENTER CH_BACK_CENTER
|
||||
#define AV_CH_SIDE_LEFT CH_SIDE_LEFT
|
||||
#define AV_CH_SIDE_RIGHT CH_SIDE_RIGHT
|
||||
#define AV_CH_TOP_CENTER CH_TOP_CENTER
|
||||
#define AV_CH_TOP_FRONT_LEFT CH_TOP_FRONT_LEFT
|
||||
#define AV_CH_TOP_FRONT_CENTER CH_TOP_FRONT_CENTER
|
||||
#define AV_CH_TOP_FRONT_RIGHT CH_TOP_FRONT_RIGHT
|
||||
#define AV_CH_TOP_BACK_LEFT CH_TOP_BACK_LEFT
|
||||
#define AV_CH_TOP_BACK_CENTER CH_TOP_BACK_CENTER
|
||||
#define AV_CH_TOP_BACK_RIGHT CH_TOP_BACK_RIGHT
|
||||
#define AV_CH_STEREO_LEFT CH_STEREO_LEFT
|
||||
#define AV_CH_STEREO_RIGHT CH_STEREO_RIGHT
|
||||
|
||||
#define AV_CH_LAYOUT_NATIVE CH_LAYOUT_NATIVE
|
||||
|
||||
#define AV_CH_LAYOUT_MONO CH_LAYOUT_MONO
|
||||
#define AV_CH_LAYOUT_STEREO CH_LAYOUT_STEREO
|
||||
#define AV_CH_LAYOUT_2_1 CH_LAYOUT_2_1
|
||||
#define AV_CH_LAYOUT_SURROUND CH_LAYOUT_SURROUND
|
||||
#define AV_CH_LAYOUT_4POINT0 CH_LAYOUT_4POINT0
|
||||
#define AV_CH_LAYOUT_2_2 CH_LAYOUT_2_2
|
||||
#define AV_CH_LAYOUT_QUAD CH_LAYOUT_QUAD
|
||||
#define AV_CH_LAYOUT_5POINT0 CH_LAYOUT_5POINT0
|
||||
#define AV_CH_LAYOUT_5POINT1 CH_LAYOUT_5POINT1
|
||||
#define AV_CH_LAYOUT_5POINT0_BACK CH_LAYOUT_5POINT0_BACK
|
||||
#define AV_CH_LAYOUT_5POINT1_BACK CH_LAYOUT_5POINT1_BACK
|
||||
#define AV_CH_LAYOUT_7POINT0 CH_LAYOUT_7POINT0
|
||||
#define AV_CH_LAYOUT_7POINT1 CH_LAYOUT_7POINT1
|
||||
#define AV_CH_LAYOUT_7POINT1_WIDE CH_LAYOUT_7POINT1_WIDE
|
||||
#define AV_CH_LAYOUT_STEREO_DOWNMIX CH_LAYOUT_STEREO_DOWNMIX
|
||||
#endif
|
||||
|
||||
#endif // USE_EXTERNAL_FFMPEG
|
||||
|
||||
class DllAvCoreInterface
|
||||
{
|
||||
public:
|
||||
virtual ~DllAvCoreInterface() {}
|
||||
virtual int av_get_bits_per_sample_fmt(enum AVSampleFormat sample_fmt) = 0;
|
||||
};
|
||||
|
||||
#if (defined USE_EXTERNAL_FFMPEG)
|
||||
|
||||
// Use direct layer
|
||||
class DllAvCore : public DllDynamic, DllAvCoreInterface
|
||||
{
|
||||
public:
|
||||
virtual ~DllAvCore() {}
|
||||
#if LIBAVCORE_VERSION_INT >= AV_VERSION_INT(0,12,0) || LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(50,38,0)
|
||||
// API added on: 2010-11-02, moved to libavutil on 2010-02-15
|
||||
virtual int av_get_bits_per_sample_fmt(enum AVSampleFormat sample_fmt) { return ::av_get_bits_per_sample_fmt(sample_fmt); }
|
||||
#else
|
||||
// from avcodec.h
|
||||
virtual int av_get_bits_per_sample_fmt(enum AVSampleFormat sample_fmt) { return ::av_get_bits_per_sample_format(sample_fmt); }
|
||||
#endif
|
||||
|
||||
// DLL faking.
|
||||
virtual bool ResolveExports() { return true; }
|
||||
virtual bool Load() {
|
||||
#if LIBAVCORE_VERSION_INT > 0
|
||||
CLog::Log(LOGDEBUG, "DllAvCore: Using libavcore system library");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
virtual void Unload() {}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
class DllAvCore : public DllDynamic, DllAvCoreInterface
|
||||
{
|
||||
DECLARE_DLL_WRAPPER(DllAvCore, DLL_PATH_LIBAVCORE)
|
||||
|
||||
LOAD_SYMBOLS()
|
||||
|
||||
DEFINE_METHOD1(int, av_get_bits_per_sample_fmt, (enum AVSampleFormat p1))
|
||||
|
||||
BEGIN_METHOD_RESOLVE()
|
||||
RESOLVE_METHOD(av_get_bits_per_sample_fmt)
|
||||
END_METHOD_RESOLVE()
|
||||
|
||||
/* dependency of libavcore */
|
||||
DllAvUtil m_dllAvUtil;
|
||||
|
||||
public:
|
||||
virtual bool Load()
|
||||
{
|
||||
if (!m_dllAvUtil.Load())
|
||||
return false;
|
||||
return DllDynamic::Load();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
331
DllAvFilter.h
Normal file
331
DllAvFilter.h
Normal file
|
|
@ -0,0 +1,331 @@
|
|||
#pragma once
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#if (defined HAVE_CONFIG_H) && (!defined WIN32)
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include "DynamicDll.h"
|
||||
#include "DllAvCore.h"
|
||||
#include "DllAvCodec.h"
|
||||
#include "utils/log.h"
|
||||
|
||||
#ifndef AV_NOWARN_DEPRECATED
|
||||
#define AV_NOWARN_DEPRECATED
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#ifndef HAVE_MMX
|
||||
#define HAVE_MMX
|
||||
#endif
|
||||
#ifndef __STDC_CONSTANT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
|
||||
#ifndef __GNUC__
|
||||
#pragma warning(disable:4244)
|
||||
#endif
|
||||
|
||||
#if (defined USE_EXTERNAL_FFMPEG)
|
||||
#if (defined HAVE_LIBAVFILTER_AVFILTER_H)
|
||||
#include <libavfilter/avfiltergraph.h>
|
||||
#elif (defined HAVE_FFMPEG_AVFILTER_H)
|
||||
#include <ffmpeg/avfiltergraph.h>
|
||||
#endif
|
||||
/* for av_vsrc_buffer_add_frame */
|
||||
#if LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,8,0)
|
||||
#include <libavfilter/avcodec.h>
|
||||
#elif LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,7,0)
|
||||
int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter,
|
||||
AVFrame *frame);
|
||||
#elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,3,0)
|
||||
int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter,
|
||||
AVFrame *frame, int64_t pts);
|
||||
#else
|
||||
int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter,
|
||||
AVFrame *frame, int64_t pts, AVRational pixel_aspect);
|
||||
#endif
|
||||
#else
|
||||
#include "libavfilter/avfiltergraph.h"
|
||||
#endif
|
||||
}
|
||||
|
||||
//#include "threads/SingleLock.h"
|
||||
|
||||
class DllAvFilterInterface
|
||||
{
|
||||
public:
|
||||
virtual ~DllAvFilterInterface() {}
|
||||
virtual int avfilter_open(AVFilterContext **filter_ctx, AVFilter *filter, const char *inst_name)=0;
|
||||
virtual void avfilter_free(AVFilterContext *filter)=0;
|
||||
virtual void avfilter_graph_free(AVFilterGraph **graph)=0;
|
||||
virtual int avfilter_graph_create_filter(AVFilterContext **filt_ctx, AVFilter *filt, const char *name, const char *args, void *opaque, AVFilterGraph *graph_ctx)=0;
|
||||
virtual AVFilter *avfilter_get_by_name(const char *name)=0;
|
||||
virtual AVFilterGraph *avfilter_graph_alloc(void)=0;
|
||||
virtual AVFilterInOut *avfilter_inout_alloc()=0;
|
||||
virtual void avfilter_inout_free(AVFilterInOut **inout)=0;
|
||||
virtual int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, AVFilterInOut **inputs, AVFilterInOut **outputs, void *log_ctx)=0;
|
||||
virtual int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx)=0;
|
||||
virtual int avfilter_poll_frame(AVFilterLink *link)=0;
|
||||
virtual int avfilter_request_frame(AVFilterLink *link)=0;
|
||||
#if LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,13,0)
|
||||
virtual int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter, AVFrame *frame, int flags)=0;
|
||||
#elif LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,7,0)
|
||||
virtual int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter, AVFrame *frame)=0;
|
||||
#elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,3,0)
|
||||
virtual int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter, AVFrame *frame, int64_t pts)=0;
|
||||
#else
|
||||
virtual int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter, AVFrame *frame, int64_t pts, AVRational pixel_aspect)=0;
|
||||
#endif
|
||||
virtual AVFilterBufferRef *avfilter_get_video_buffer(AVFilterLink *link, int perms, int w, int h)=0;
|
||||
virtual void avfilter_unref_buffer(AVFilterBufferRef *ref)=0;
|
||||
virtual int avfilter_link(AVFilterContext *src, unsigned srcpad, AVFilterContext *dst, unsigned dstpad)=0;
|
||||
};
|
||||
|
||||
#if (defined USE_EXTERNAL_FFMPEG)
|
||||
// Use direct mapping
|
||||
class DllAvFilter : public DllDynamic, DllAvFilterInterface
|
||||
{
|
||||
public:
|
||||
virtual ~DllAvFilter() {}
|
||||
virtual int avfilter_open(AVFilterContext **filter_ctx, AVFilter *filter, const char *inst_name)
|
||||
{
|
||||
return ::avfilter_open(filter_ctx, filter, inst_name);
|
||||
}
|
||||
virtual void avfilter_free(AVFilterContext *filter)
|
||||
{
|
||||
::avfilter_free(filter);
|
||||
}
|
||||
virtual void avfilter_graph_free(AVFilterGraph **graph)
|
||||
{
|
||||
#if LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(1,76,0)
|
||||
::avfilter_graph_free(graph);
|
||||
#else
|
||||
::avfilter_graph_free(*graph);
|
||||
*graph = NULL;
|
||||
#endif
|
||||
}
|
||||
void avfilter_register_all()
|
||||
{
|
||||
::avfilter_register_all();
|
||||
}
|
||||
virtual int avfilter_graph_create_filter(AVFilterContext **filt_ctx, AVFilter *filt, const char *name, const char *args, void *opaque, AVFilterGraph *graph_ctx) { return ::avfilter_graph_create_filter(filt_ctx, filt, name, args, opaque, graph_ctx); }
|
||||
virtual AVFilter *avfilter_get_by_name(const char *name) { return ::avfilter_get_by_name(name); }
|
||||
virtual AVFilterGraph *avfilter_graph_alloc() { return ::avfilter_graph_alloc(); }
|
||||
virtual AVFilterInOut *avfilter_inout_alloc()
|
||||
{
|
||||
#if LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,17,0)
|
||||
return ::avfilter_inout_alloc();
|
||||
#else
|
||||
return (AVFilterInOut*)::av_mallocz(sizeof(AVFilterInOut));
|
||||
#endif
|
||||
}
|
||||
virtual void avfilter_inout_free(AVFilterInOut **inout)
|
||||
{
|
||||
#if LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,17,0)
|
||||
::avfilter_inout_free(inout);
|
||||
#else
|
||||
*inout = NULL;
|
||||
#endif
|
||||
}
|
||||
virtual int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, AVFilterInOut **inputs, AVFilterInOut **outputs, void *log_ctx)
|
||||
{
|
||||
#if LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,16,0)
|
||||
return ::avfilter_graph_parse(graph, filters, inputs, outputs, log_ctx);
|
||||
#elif LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,15,1)
|
||||
return ::avfilter_graph_parse(graph, filters, *inputs, *outputs, log_ctx);
|
||||
#else
|
||||
return ::avfilter_graph_parse(graph, filters, *inputs, *outputs, (AVClass*)log_ctx);
|
||||
#endif
|
||||
}
|
||||
virtual int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx)
|
||||
{
|
||||
#if LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,15,1)
|
||||
return ::avfilter_graph_config(graphctx, log_ctx);
|
||||
#else
|
||||
return ::avfilter_graph_config(graphctx, (AVClass*)log_ctx);
|
||||
#endif
|
||||
}
|
||||
virtual int avfilter_poll_frame(AVFilterLink *link) { return ::avfilter_poll_frame(link); }
|
||||
virtual int avfilter_request_frame(AVFilterLink *link) { return ::avfilter_request_frame(link); }
|
||||
#if LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,13,0)
|
||||
virtual int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter, AVFrame *frame, int flags) { return ::av_vsrc_buffer_add_frame(buffer_filter, frame, flags); }
|
||||
#elif LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,7,0)
|
||||
virtual int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter, AVFrame *frame) { return ::av_vsrc_buffer_add_frame(buffer_filter, frame); }
|
||||
#elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,3,0)
|
||||
virtual int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter, AVFrame *frame, int64_t pts) { return ::av_vsrc_buffer_add_frame(buffer_filter, frame, pts); }
|
||||
#else
|
||||
virtual int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter, AVFrame *frame, int64_t pts, AVRational pixel_aspect) { return ::av_vsrc_buffer_add_frame(buffer_filter, frame, pts, pixel_aspect); }
|
||||
#endif
|
||||
virtual AVFilterBufferRef *avfilter_get_video_buffer(AVFilterLink *link, int perms, int w, int h) { return ::avfilter_get_video_buffer(link, perms, w, h); }
|
||||
virtual void avfilter_unref_buffer(AVFilterBufferRef *ref) { ::avfilter_unref_buffer(ref); }
|
||||
virtual int avfilter_link(AVFilterContext *src, unsigned srcpad, AVFilterContext *dst, unsigned dstpad) { return ::avfilter_link(src, srcpad, dst, dstpad); }
|
||||
// DLL faking.
|
||||
virtual bool ResolveExports() { return true; }
|
||||
virtual bool Load() {
|
||||
CLog::Log(LOGDEBUG, "DllAvFilter: Using libavfilter system library");
|
||||
return true;
|
||||
}
|
||||
virtual void Unload() {}
|
||||
};
|
||||
#else
|
||||
class DllAvFilter : public DllDynamic, DllAvFilterInterface
|
||||
{
|
||||
DECLARE_DLL_WRAPPER(DllAvFilter, DLL_PATH_LIBAVFILTER)
|
||||
|
||||
LOAD_SYMBOLS()
|
||||
|
||||
DEFINE_METHOD3(int, avfilter_open_dont_call, (AVFilterContext **p1, AVFilter *p2, const char *p3))
|
||||
DEFINE_METHOD1(void, avfilter_free_dont_call, (AVFilterContext *p1))
|
||||
#if LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(1,76,0)
|
||||
DEFINE_METHOD1(void, avfilter_graph_free_dont_call, (AVFilterGraph **p1))
|
||||
#else
|
||||
DEFINE_METHOD1(void, avfilter_graph_free_dont_call, (AVFilterGraph *p1))
|
||||
#endif
|
||||
DEFINE_METHOD0(void, avfilter_register_all_dont_call)
|
||||
DEFINE_METHOD6(int, avfilter_graph_create_filter, (AVFilterContext **p1, AVFilter *p2, const char *p3, const char *p4, void *p5, AVFilterGraph *p6))
|
||||
DEFINE_METHOD1(AVFilter*, avfilter_get_by_name, (const char *p1))
|
||||
DEFINE_METHOD0(AVFilterGraph*, avfilter_graph_alloc)
|
||||
#if LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,17,0)
|
||||
DEFINE_METHOD0(AVFilterInOut*, avfilter_inout_alloc_dont_call)
|
||||
DEFINE_METHOD1(void, avfilter_inout_free_dont_call, (AVFilterInOut **p1))
|
||||
#endif
|
||||
#if LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,16,0)
|
||||
DEFINE_METHOD5(int, avfilter_graph_parse_dont_call, (AVFilterGraph *p1, const char *p2, AVFilterInOut **p3, AVFilterInOut **p4, void *p5))
|
||||
#elif LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,15,1)
|
||||
DEFINE_METHOD5(int, avfilter_graph_parse_dont_call, (AVFilterGraph *p1, const char *p2, AVFilterInOut *p3, AVFilterInOut *p4, void *p5))
|
||||
#else
|
||||
DEFINE_METHOD5(int, avfilter_graph_parse_dont_call, (AVFilterGraph *p1, const char *p2, AVFilterInOut *p3, AVFilterInOut *p4, AVClass *p5))
|
||||
#endif
|
||||
#if LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,15,1)
|
||||
DEFINE_METHOD2(int, avfilter_graph_config_dont_call, (AVFilterGraph *p1, void *p2))
|
||||
#else
|
||||
DEFINE_METHOD2(int, avfilter_graph_config_dont_call, (AVFilterGraph *p1, AVClass *p2))
|
||||
#endif
|
||||
#ifdef _LINUX
|
||||
DEFINE_METHOD1(int, avfilter_poll_frame, (AVFilterLink *p1))
|
||||
DEFINE_METHOD1(int, avfilter_request_frame, (AVFilterLink* p1))
|
||||
#else
|
||||
DEFINE_FUNC_ALIGNED1(int, __cdecl, avfilter_poll_frame, AVFilterLink *)
|
||||
DEFINE_FUNC_ALIGNED1(int, __cdecl, avfilter_request_frame, AVFilterLink*)
|
||||
#endif
|
||||
#if LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,13,0)
|
||||
DEFINE_METHOD3(int, av_vsrc_buffer_add_frame, (AVFilterContext *p1, AVFrame *p2, int p3))
|
||||
#elif LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,7,0)
|
||||
DEFINE_METHOD2(int, av_vsrc_buffer_add_frame, (AVFilterContext *p1, AVFrame *p2))
|
||||
#elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,3,0)
|
||||
DEFINE_METHOD3(int, av_vsrc_buffer_add_frame, (AVFilterContext *p1, AVFrame *p2, int64_t p3))
|
||||
#else
|
||||
DEFINE_METHOD4(int, av_vsrc_buffer_add_frame, (AVFilterContext *p1, AVFrame *p2, int64_t p3, AVRational p4))
|
||||
#endif
|
||||
DEFINE_METHOD4(AVFilterBufferRef*, avfilter_get_video_buffer, (AVFilterLink *p1, int p2, int p3, int p4))
|
||||
DEFINE_METHOD1(void, avfilter_unref_buffer, (AVFilterBufferRef *p1))
|
||||
DEFINE_METHOD4(int, avfilter_link, (AVFilterContext *p1, unsigned p2, AVFilterContext *p3, unsigned p4))
|
||||
|
||||
BEGIN_METHOD_RESOLVE()
|
||||
RESOLVE_METHOD_RENAME(avfilter_open, avfilter_open_dont_call)
|
||||
RESOLVE_METHOD_RENAME(avfilter_free, avfilter_free_dont_call)
|
||||
RESOLVE_METHOD_RENAME(avfilter_graph_free, avfilter_graph_free_dont_call)
|
||||
RESOLVE_METHOD_RENAME(avfilter_register_all, avfilter_register_all_dont_call)
|
||||
RESOLVE_METHOD(avfilter_graph_create_filter)
|
||||
RESOLVE_METHOD(avfilter_get_by_name)
|
||||
RESOLVE_METHOD(avfilter_graph_alloc)
|
||||
#if LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,17,0)
|
||||
RESOLVE_METHOD_RENAME(avfilter_inout_alloc, avfilter_inout_alloc_dont_call)
|
||||
RESOLVE_METHOD_RENAME(avfilter_inout_free, avfilter_inout_free_dont_call)
|
||||
#endif
|
||||
RESOLVE_METHOD_RENAME(avfilter_graph_parse, avfilter_graph_parse_dont_call)
|
||||
RESOLVE_METHOD_RENAME(avfilter_graph_config, avfilter_graph_config_dont_call)
|
||||
RESOLVE_METHOD(avfilter_poll_frame)
|
||||
RESOLVE_METHOD(avfilter_request_frame)
|
||||
RESOLVE_METHOD(av_vsrc_buffer_add_frame)
|
||||
RESOLVE_METHOD(avfilter_get_video_buffer)
|
||||
RESOLVE_METHOD(avfilter_unref_buffer)
|
||||
RESOLVE_METHOD(avfilter_link)
|
||||
END_METHOD_RESOLVE()
|
||||
|
||||
/* dependencies of libavfilter */
|
||||
DllAvUtil m_dllAvUtil;
|
||||
|
||||
public:
|
||||
int avfilter_open(AVFilterContext **filter_ctx, AVFilter *filter, const char *inst_name)
|
||||
{
|
||||
return avfilter_open_dont_call(filter_ctx, filter, inst_name);
|
||||
}
|
||||
void avfilter_free(AVFilterContext *filter)
|
||||
{
|
||||
avfilter_free_dont_call(filter);
|
||||
}
|
||||
void avfilter_graph_free(AVFilterGraph **graph)
|
||||
{
|
||||
#if LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(1,76,0)
|
||||
avfilter_graph_free_dont_call(graph);
|
||||
#else
|
||||
avfilter_graph_free_dont_call(*graph);
|
||||
m_dllAvUtil.av_freep(graph);
|
||||
#endif
|
||||
}
|
||||
void avfilter_register_all()
|
||||
{
|
||||
avfilter_register_all_dont_call();
|
||||
}
|
||||
AVFilterInOut* avfilter_inout_alloc()
|
||||
{
|
||||
#if LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,17,0)
|
||||
return avfilter_inout_alloc_dont_call();
|
||||
#else
|
||||
return (AVFilterInOut*)m_dllAvUtil.av_mallocz(sizeof(AVFilterInOut));
|
||||
#endif
|
||||
}
|
||||
int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, AVFilterInOut **inputs, AVFilterInOut **outputs, void *log_ctx)
|
||||
{
|
||||
#if LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,16,0)
|
||||
return avfilter_graph_parse_dont_call(graph, filters, inputs, outputs, log_ctx);
|
||||
#elif LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,15,1)
|
||||
return avfilter_graph_parse_dont_call(graph, filters, *inputs, *outputs, log_ctx);
|
||||
#else
|
||||
return avfilter_graph_parse_dont_call(graph, filters, *inputs, *outputs, (AVClass*)log_ctx);
|
||||
#endif
|
||||
}
|
||||
void avfilter_inout_free(AVFilterInOut **inout)
|
||||
{
|
||||
#if LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,17,0)
|
||||
avfilter_inout_free_dont_call(inout);
|
||||
#else
|
||||
*inout = NULL;
|
||||
#endif
|
||||
}
|
||||
int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx)
|
||||
{
|
||||
#if LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(2,15,1)
|
||||
return avfilter_graph_config_dont_call(graphctx, log_ctx);
|
||||
#else
|
||||
return avfilter_graph_config_dont_call(graphctx, (AVClass*)log_ctx);
|
||||
#endif
|
||||
}
|
||||
virtual bool Load()
|
||||
{
|
||||
if (!m_dllAvUtil.Load())
|
||||
return false;
|
||||
return DllDynamic::Load();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
333
DllAvFormat.h
Normal file
333
DllAvFormat.h
Normal file
|
|
@ -0,0 +1,333 @@
|
|||
#pragma once
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#if (defined HAVE_CONFIG_H) && (!defined WIN32)
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include "DynamicDll.h"
|
||||
#include "DllAvCodec.h"
|
||||
|
||||
#ifndef AV_NOWARN_DEPRECATED
|
||||
#define AV_NOWARN_DEPRECATED
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#ifndef HAVE_MMX
|
||||
#define HAVE_MMX
|
||||
#endif
|
||||
#ifndef __STDC_CONSTANT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
#ifndef __GNUC__
|
||||
#pragma warning(disable:4244)
|
||||
#endif
|
||||
#if (defined USE_EXTERNAL_FFMPEG)
|
||||
#if (defined HAVE_LIBAVFORMAT_AVFORMAT_H)
|
||||
#include <libavformat/avformat.h>
|
||||
#else
|
||||
#include <ffmpeg/avformat.h>
|
||||
#endif
|
||||
/* libavformat/riff.h is not a public header, so include it here */
|
||||
//#include "libavformat/riff.h"
|
||||
#else
|
||||
#include "libavformat/avformat.h"
|
||||
//#include "libavformat/riff.h"
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Flag introduced without a version bump */
|
||||
#ifndef AVSEEK_FORCE
|
||||
#define AVSEEK_FORCE 0x20000
|
||||
#endif
|
||||
|
||||
typedef int64_t offset_t;
|
||||
|
||||
class DllAvFormatInterface
|
||||
{
|
||||
public:
|
||||
virtual ~DllAvFormatInterface() {}
|
||||
virtual void av_register_all_dont_call(void)=0;
|
||||
virtual AVInputFormat *av_find_input_format(const char *short_name)=0;
|
||||
virtual int url_feof(ByteIOContext *s)=0;
|
||||
virtual AVMetadataTag *av_metadata_get(AVMetadata *m, const char *key, const AVMetadataTag *prev, int flags)=0;
|
||||
virtual void av_close_input_file(AVFormatContext *s)=0;
|
||||
virtual void av_close_input_stream(AVFormatContext *s)=0;
|
||||
virtual int av_read_frame(AVFormatContext *s, AVPacket *pkt)=0;
|
||||
virtual int av_read_play(AVFormatContext *s)=0;
|
||||
virtual int av_read_pause(AVFormatContext *s)=0;
|
||||
virtual int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)=0;
|
||||
#if (!defined USE_EXTERNAL_FFMPEG)
|
||||
virtual int av_find_stream_info_dont_call(AVFormatContext *ic)=0;
|
||||
#endif
|
||||
virtual int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, AVInputFormat *fmt, int buf_size, AVFormatParameters *ap)=0;
|
||||
virtual void url_set_interrupt_cb(URLInterruptCB *interrupt_cb)=0;
|
||||
virtual int av_open_input_stream(AVFormatContext **ic_ptr, ByteIOContext *pb, const char *filename, AVInputFormat *fmt, AVFormatParameters *ap)=0;
|
||||
virtual AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened)=0;
|
||||
virtual AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max)=0;
|
||||
virtual int av_probe_input_buffer(ByteIOContext *pb, AVInputFormat **fmt, const char *filename, void *logctx, unsigned int offset, unsigned int max_probe_size)=0;
|
||||
virtual void dump_format(AVFormatContext *ic, int index, const char *url, int is_output)=0;
|
||||
virtual int url_fdopen(ByteIOContext **s, URLContext *h)=0;
|
||||
virtual int url_fopen(ByteIOContext **s, const char *filename, int flags)=0;
|
||||
virtual int url_fclose(ByteIOContext *s)=0;
|
||||
virtual int url_open_dyn_buf(ByteIOContext **s)=0;
|
||||
virtual int url_close_dyn_buf(ByteIOContext *s, uint8_t **pbuffer)=0;
|
||||
virtual offset_t url_fseek(ByteIOContext *s, offset_t offset, int whence)=0;
|
||||
virtual int get_buffer(ByteIOContext *s, unsigned char *buf, int size)=0;
|
||||
virtual int get_partial_buffer(ByteIOContext *s, unsigned char *buf, int size)=0;
|
||||
virtual void put_byte(ByteIOContext *s, int b)=0;
|
||||
virtual void put_buffer(ByteIOContext *s, const unsigned char *buf, int size)=0;
|
||||
virtual void put_be24(ByteIOContext *s, unsigned int val)=0;
|
||||
virtual void put_be32(ByteIOContext *s, unsigned int val)=0;
|
||||
virtual void put_be16(ByteIOContext *s, unsigned int val)=0;
|
||||
virtual AVFormatContext *avformat_alloc_context(void)=0;
|
||||
virtual AVStream *av_new_stream(AVFormatContext *s, int id)=0;
|
||||
virtual AVOutputFormat *av_guess_format(const char *short_name, const char *filename, const char *mime_type)=0;
|
||||
virtual int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap)=0;
|
||||
virtual ByteIOContext *av_alloc_put_byte(unsigned char *buffer, int buffer_size, int write_flag, void *opaque,
|
||||
int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
|
||||
int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
|
||||
offset_t (*seek)(void *opaque, offset_t offset, int whence))=0;
|
||||
virtual int av_write_header (AVFormatContext *s)=0;
|
||||
virtual int av_write_trailer(AVFormatContext *s)=0;
|
||||
virtual int av_write_frame (AVFormatContext *s, AVPacket *pkt)=0;
|
||||
virtual int av_metadata_set2(AVMetadata **pm, const char *key, const char *value, int flags)=0;
|
||||
virtual int64_t av_gettime(void)=0;
|
||||
};
|
||||
|
||||
#if (defined USE_EXTERNAL_FFMPEG)
|
||||
|
||||
// Use direct mapping
|
||||
class DllAvFormat : public DllDynamic, DllAvFormatInterface
|
||||
{
|
||||
public:
|
||||
virtual ~DllAvFormat() {}
|
||||
virtual void av_register_all()
|
||||
{
|
||||
return ::av_register_all();
|
||||
}
|
||||
virtual void av_register_all_dont_call() { *(int* )0x0 = 0; }
|
||||
virtual AVInputFormat *av_find_input_format(const char *short_name) { return ::av_find_input_format(short_name); }
|
||||
virtual int url_feof(ByteIOContext *s) { return ::url_feof(s); }
|
||||
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(52,31,0)
|
||||
// API added on: 2009-03-01
|
||||
virtual AVMetadataTag *av_metadata_get(AVMetadata *m, const char *key, const AVMetadataTag *prev, int flags){ return ::av_metadata_get(m, key, prev, flags); }
|
||||
#else
|
||||
virtual AVMetadataTag *av_metadata_get(AVMetadata *m, const char *key, const AVMetadataTag *prev, int flags){ return NULL; }
|
||||
#endif
|
||||
virtual void av_close_input_file(AVFormatContext *s) { ::av_close_input_file(s); }
|
||||
virtual void av_close_input_stream(AVFormatContext *s) { ::av_close_input_stream(s); }
|
||||
virtual int av_read_frame(AVFormatContext *s, AVPacket *pkt) { return ::av_read_frame(s, pkt); }
|
||||
virtual int av_read_play(AVFormatContext *s) { return ::av_read_play(s); }
|
||||
virtual int av_read_pause(AVFormatContext *s) { return ::av_read_pause(s); }
|
||||
virtual int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { return ::av_seek_frame(s, stream_index, timestamp, flags); }
|
||||
virtual int av_find_stream_info(AVFormatContext *ic)
|
||||
{
|
||||
return ::av_find_stream_info(ic);
|
||||
}
|
||||
virtual int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, AVInputFormat *fmt, int buf_size, AVFormatParameters *ap) { return ::av_open_input_file(ic_ptr, filename, fmt, buf_size, ap); }
|
||||
virtual void url_set_interrupt_cb(URLInterruptCB *interrupt_cb) { ::url_set_interrupt_cb(interrupt_cb); }
|
||||
virtual int av_open_input_stream(AVFormatContext **ic_ptr, ByteIOContext *pb, const char *filename, AVInputFormat *fmt, AVFormatParameters *ap) { return ::av_open_input_stream(ic_ptr, pb, filename, fmt, ap); }
|
||||
virtual AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened) {return ::av_probe_input_format(pd, is_opened); }
|
||||
virtual AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max) {*score_max = 100; return ::av_probe_input_format(pd, is_opened); } // Use av_probe_input_format, this is not exported by ffmpeg's headers
|
||||
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(52,98,0)
|
||||
// API added on: 2010-02-08
|
||||
virtual int av_probe_input_buffer(ByteIOContext *pb, AVInputFormat **fmt, const char *filename, void *logctx, unsigned int offset, unsigned int max_probe_size) { return ::av_probe_input_buffer(pb, fmt, filename, logctx, offset, max_probe_size); }
|
||||
#else
|
||||
virtual int av_probe_input_buffer(ByteIOContext *pb, AVInputFormat **fmt, const char *filename, void *logctx, unsigned int offset, unsigned int max_probe_size) { return -1; }
|
||||
#endif
|
||||
virtual void dump_format(AVFormatContext *ic, int index, const char *url, int is_output) { ::dump_format(ic, index, url, is_output); }
|
||||
virtual int url_fdopen(ByteIOContext **s, URLContext *h) { return ::url_fdopen(s, h); }
|
||||
virtual int url_fopen(ByteIOContext **s, const char *filename, int flags) { return ::url_fopen(s, filename, flags); }
|
||||
virtual int url_fclose(ByteIOContext *s) { return ::url_fclose(s); }
|
||||
virtual int url_open_dyn_buf(ByteIOContext **s) { return ::url_open_dyn_buf(s); }
|
||||
virtual int url_close_dyn_buf(ByteIOContext *s, uint8_t **pbuffer) { return ::url_close_dyn_buf(s, pbuffer); }
|
||||
virtual offset_t url_fseek(ByteIOContext *s, offset_t offset, int whence) { return ::url_fseek(s, offset, whence); }
|
||||
virtual int get_buffer(ByteIOContext *s, unsigned char *buf, int size) { return ::get_buffer(s, buf, size); }
|
||||
virtual int get_partial_buffer(ByteIOContext *s, unsigned char *buf, int size) { return ::get_partial_buffer(s, buf, size); }
|
||||
virtual void put_byte(ByteIOContext *s, int b) { ::put_byte(s, b); }
|
||||
virtual void put_buffer(ByteIOContext *s, const unsigned char *buf, int size) { ::put_buffer(s, buf, size); }
|
||||
virtual void put_be24(ByteIOContext *s, unsigned int val) { ::put_be24(s, val); }
|
||||
virtual void put_be32(ByteIOContext *s, unsigned int val) { ::put_be32(s, val); }
|
||||
virtual void put_be16(ByteIOContext *s, unsigned int val) { ::put_be16(s, val); }
|
||||
virtual AVFormatContext *avformat_alloc_context() { return ::avformat_alloc_context(); }
|
||||
virtual AVStream *av_new_stream(AVFormatContext *s, int id) { return ::av_new_stream(s, id); }
|
||||
#if LIBAVFORMAT_VERSION_INT < (52<<16 | 45<<8)
|
||||
virtual AVOutputFormat *av_guess_format(const char *short_name, const char *filename, const char *mime_type) { return ::guess_format(short_name, filename, mime_type); }
|
||||
#else
|
||||
virtual AVOutputFormat *av_guess_format(const char *short_name, const char *filename, const char *mime_type) { return ::av_guess_format(short_name, filename, mime_type); }
|
||||
#endif
|
||||
virtual int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap) { return ::av_set_parameters(s, ap); }
|
||||
virtual ByteIOContext *av_alloc_put_byte(unsigned char *buffer, int buffer_size, int write_flag, void *opaque,
|
||||
int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
|
||||
int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
|
||||
offset_t (*seek)(void *opaque, offset_t offset, int whence)) { return ::av_alloc_put_byte(buffer, buffer_size, write_flag, opaque, read_packet, write_packet, seek); }
|
||||
virtual int av_write_header (AVFormatContext *s) { return ::av_write_header (s); }
|
||||
virtual int av_write_trailer(AVFormatContext *s) { return ::av_write_trailer(s); }
|
||||
virtual int av_write_frame (AVFormatContext *s, AVPacket *pkt) { return ::av_write_frame(s, pkt); }
|
||||
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(52,43,0)
|
||||
// API added on: 2009-12-13
|
||||
virtual int av_metadata_set2(AVMetadata **pm, const char *key, const char *value, int flags) { return ::av_metadata_set2(pm, key, value, flags); }
|
||||
#elif LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(52,31,0)
|
||||
// API added on: 2009-03-01
|
||||
virtual int av_metadata_set2(AVMetadata **pm, const char *key, const char *value, int flags) { return ::av_metadata_set(pm, key, value); }
|
||||
#else
|
||||
virtual int av_metadata_set2(AVMetadata **pm, const char *key, const char *value, int flags) { return -1; }
|
||||
#endif
|
||||
virtual int64_t av_gettime(void) { return ::av_gettime(); }
|
||||
|
||||
// DLL faking.
|
||||
virtual bool ResolveExports() { return true; }
|
||||
virtual bool Load() {
|
||||
CLog::Log(LOGDEBUG, "DllAvFormat: Using libavformat system library");
|
||||
return true;
|
||||
}
|
||||
virtual void Unload() {}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
class DllAvFormat : public DllDynamic, DllAvFormatInterface
|
||||
{
|
||||
DECLARE_DLL_WRAPPER(DllAvFormat, DLL_PATH_LIBAVFORMAT)
|
||||
|
||||
LOAD_SYMBOLS()
|
||||
|
||||
DEFINE_METHOD0(void, av_register_all_dont_call)
|
||||
DEFINE_METHOD1(AVInputFormat*, av_find_input_format, (const char *p1))
|
||||
DEFINE_METHOD1(int, url_feof, (ByteIOContext *p1))
|
||||
DEFINE_METHOD4(AVMetadataTag*, av_metadata_get, (AVMetadata *p1, const char *p2, const AVMetadataTag *p3, int p4))
|
||||
DEFINE_METHOD1(void, av_close_input_file, (AVFormatContext *p1))
|
||||
DEFINE_METHOD1(void, av_close_input_stream, (AVFormatContext *p1))
|
||||
DEFINE_METHOD1(int, av_read_play, (AVFormatContext *p1))
|
||||
DEFINE_METHOD1(int, av_read_pause, (AVFormatContext *p1))
|
||||
DEFINE_FUNC_ALIGNED2(int, __cdecl, av_read_frame, AVFormatContext *, AVPacket *)
|
||||
DEFINE_FUNC_ALIGNED4(int, __cdecl, av_seek_frame, AVFormatContext*, int, int64_t, int)
|
||||
DEFINE_FUNC_ALIGNED1(int, __cdecl, av_find_stream_info_dont_call, AVFormatContext*)
|
||||
DEFINE_FUNC_ALIGNED5(int, __cdecl, av_open_input_file, AVFormatContext**, const char *, AVInputFormat *, int, AVFormatParameters *)
|
||||
DEFINE_FUNC_ALIGNED5(int,__cdecl, av_open_input_stream, AVFormatContext **, ByteIOContext *, const char *, AVInputFormat *, AVFormatParameters *)
|
||||
DEFINE_FUNC_ALIGNED2(AVInputFormat*, __cdecl, av_probe_input_format, AVProbeData*, int)
|
||||
DEFINE_FUNC_ALIGNED3(AVInputFormat*, __cdecl, av_probe_input_format2, AVProbeData*, int, int*)
|
||||
DEFINE_FUNC_ALIGNED6(int, __cdecl, av_probe_input_buffer, ByteIOContext *, AVInputFormat **, const char *, void *, unsigned int, unsigned int)
|
||||
DEFINE_FUNC_ALIGNED3(int, __cdecl, get_buffer, ByteIOContext*, unsigned char *, int)
|
||||
DEFINE_FUNC_ALIGNED3(int, __cdecl, get_partial_buffer, ByteIOContext*, unsigned char *, int)
|
||||
DEFINE_FUNC_ALIGNED2(void, __cdecl, put_byte, ByteIOContext*, int)
|
||||
DEFINE_FUNC_ALIGNED3(void, __cdecl, put_buffer, ByteIOContext*, const unsigned char *, int)
|
||||
DEFINE_FUNC_ALIGNED2(void, __cdecl, put_be24, ByteIOContext*, unsigned int)
|
||||
DEFINE_FUNC_ALIGNED2(void, __cdecl, put_be32, ByteIOContext*, unsigned int)
|
||||
DEFINE_FUNC_ALIGNED2(void, __cdecl, put_be16, ByteIOContext*, unsigned int)
|
||||
DEFINE_METHOD1(void, url_set_interrupt_cb, (URLInterruptCB *p1))
|
||||
DEFINE_METHOD4(void, dump_format, (AVFormatContext *p1, int p2, const char *p3, int p4))
|
||||
DEFINE_METHOD2(int, url_fdopen, (ByteIOContext **p1, URLContext *p2))
|
||||
DEFINE_METHOD3(int, url_fopen, (ByteIOContext **p1, const char *p2, int p3))
|
||||
DEFINE_METHOD1(int, url_fclose, (ByteIOContext *p1))
|
||||
DEFINE_METHOD1(int, url_open_dyn_buf, (ByteIOContext **p1))
|
||||
DEFINE_METHOD2(int, url_close_dyn_buf, (ByteIOContext *p1, uint8_t **p2))
|
||||
DEFINE_METHOD3(offset_t, url_fseek, (ByteIOContext *p1, offset_t p2, int p3))
|
||||
DEFINE_METHOD0(AVFormatContext *, avformat_alloc_context)
|
||||
DEFINE_METHOD2(AVStream *, av_new_stream, (AVFormatContext *p1, int p2))
|
||||
#if LIBAVFORMAT_VERSION_INT < (52<<16 | 45<<8)
|
||||
DEFINE_METHOD3(AVOutputFormat *, guess_format, (const char *p1, const char *p2, const char *p3))
|
||||
#else
|
||||
DEFINE_METHOD3(AVOutputFormat *, av_guess_format, (const char *p1, const char *p2, const char *p3))
|
||||
#endif
|
||||
DEFINE_METHOD2(int, av_set_parameters, (AVFormatContext *p1, AVFormatParameters *p2));
|
||||
DEFINE_METHOD7(ByteIOContext *, av_alloc_put_byte, (unsigned char *p1, int p2, int p3, void *p4,
|
||||
int(*p5)(void *opaque, uint8_t *buf, int buf_size),
|
||||
int(*p6)(void *opaque, uint8_t *buf, int buf_size),
|
||||
offset_t(*p7)(void *opaque, offset_t offset, int whence)))
|
||||
DEFINE_METHOD1(int, av_write_header , (AVFormatContext *p1))
|
||||
DEFINE_METHOD1(int, av_write_trailer, (AVFormatContext *p1))
|
||||
DEFINE_METHOD2(int, av_write_frame , (AVFormatContext *p1, AVPacket *p2))
|
||||
DEFINE_METHOD4(int, av_metadata_set2, (AVMetadata **p1, const char *p2, const char *p3, int p4))
|
||||
DEFINE_METHOD0(int64_t, av_gettime);
|
||||
BEGIN_METHOD_RESOLVE()
|
||||
RESOLVE_METHOD_RENAME(av_register_all, av_register_all_dont_call)
|
||||
RESOLVE_METHOD(av_find_input_format)
|
||||
RESOLVE_METHOD(url_feof)
|
||||
RESOLVE_METHOD(av_metadata_get)
|
||||
RESOLVE_METHOD(av_close_input_file)
|
||||
RESOLVE_METHOD(av_close_input_stream)
|
||||
RESOLVE_METHOD(av_read_frame)
|
||||
RESOLVE_METHOD(av_read_play)
|
||||
RESOLVE_METHOD(av_read_pause)
|
||||
RESOLVE_METHOD(av_seek_frame)
|
||||
RESOLVE_METHOD_RENAME(av_find_stream_info, av_find_stream_info_dont_call)
|
||||
RESOLVE_METHOD(av_open_input_file)
|
||||
RESOLVE_METHOD(url_set_interrupt_cb)
|
||||
RESOLVE_METHOD(av_open_input_stream)
|
||||
RESOLVE_METHOD(av_probe_input_format)
|
||||
RESOLVE_METHOD(av_probe_input_format2)
|
||||
RESOLVE_METHOD(av_probe_input_buffer)
|
||||
RESOLVE_METHOD(dump_format)
|
||||
RESOLVE_METHOD(url_fdopen)
|
||||
RESOLVE_METHOD(url_fopen)
|
||||
RESOLVE_METHOD(url_fclose)
|
||||
RESOLVE_METHOD(url_open_dyn_buf)
|
||||
RESOLVE_METHOD(url_close_dyn_buf)
|
||||
RESOLVE_METHOD(url_fseek)
|
||||
RESOLVE_METHOD(get_buffer)
|
||||
RESOLVE_METHOD(get_partial_buffer)
|
||||
RESOLVE_METHOD(put_byte)
|
||||
RESOLVE_METHOD(put_buffer)
|
||||
RESOLVE_METHOD(put_be24)
|
||||
RESOLVE_METHOD(put_be32)
|
||||
RESOLVE_METHOD(put_be16)
|
||||
RESOLVE_METHOD(avformat_alloc_context)
|
||||
RESOLVE_METHOD(av_new_stream)
|
||||
#if LIBAVFORMAT_VERSION_INT < (52<<16 | 45<<8)
|
||||
RESOLVE_METHOD(guess_format)
|
||||
#else
|
||||
RESOLVE_METHOD(av_guess_format)
|
||||
#endif
|
||||
RESOLVE_METHOD(av_set_parameters)
|
||||
RESOLVE_METHOD(av_alloc_put_byte)
|
||||
RESOLVE_METHOD(av_write_header)
|
||||
RESOLVE_METHOD(av_write_trailer)
|
||||
RESOLVE_METHOD(av_write_frame)
|
||||
RESOLVE_METHOD(av_metadata_set2)
|
||||
RESOLVE_METHOD(av_gettime)
|
||||
END_METHOD_RESOLVE()
|
||||
|
||||
/* dependencies of libavformat */
|
||||
DllAvCodec m_dllAvCodec;
|
||||
// DllAvCore loaded implicitely by m_dllAvCodec
|
||||
// DllAvUtil loaded implicitely by m_dllAvCodec
|
||||
|
||||
public:
|
||||
void av_register_all()
|
||||
{
|
||||
av_register_all_dont_call();
|
||||
}
|
||||
int av_find_stream_info(AVFormatContext *ic)
|
||||
{
|
||||
return(av_find_stream_info_dont_call(ic));
|
||||
}
|
||||
|
||||
virtual bool Load()
|
||||
{
|
||||
if (!m_dllAvCodec.Load())
|
||||
return false;
|
||||
return DllDynamic::Load();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
216
DllAvUtil.h
Normal file
216
DllAvUtil.h
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
#pragma once
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#if (defined HAVE_CONFIG_H) && (!defined WIN32)
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include "DynamicDll.h"
|
||||
#include "utils/log.h"
|
||||
|
||||
#ifndef __GNUC__
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4244)
|
||||
#endif
|
||||
|
||||
#ifndef AV_NOWARN_DEPRECATED
|
||||
#define AV_NOWARN_DEPRECATED
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#if (defined USE_EXTERNAL_FFMPEG)
|
||||
#if (defined HAVE_LIBAVUTIL_AVUTIL_H)
|
||||
#include <libavutil/avutil.h>
|
||||
#include <libavutil/crc.h>
|
||||
#include <libavutil/fifo.h>
|
||||
// for LIBAVCODEC_VERSION_INT:
|
||||
#include <libavcodec/avcodec.h>
|
||||
#elif (defined HAVE_FFMPEG_AVUTIL_H)
|
||||
#include <ffmpeg/avutil.h>
|
||||
#include <ffmpeg/crc.h>
|
||||
#include <ffmpeg/fifo.h>
|
||||
// for LIBAVCODEC_VERSION_INT:
|
||||
#include <ffmpeg/avcodec.h>
|
||||
#endif
|
||||
#if defined(HAVE_LIBAVUTIL_OPT_H)
|
||||
#include <libavutil/opt.h>
|
||||
#elif defined(HAVE_LIBAVCODEC_AVCODEC_H)
|
||||
#include <libavcodec/opt.h>
|
||||
#else
|
||||
#include <ffmpeg/opt.h>
|
||||
#endif
|
||||
#if defined(HAVE_LIBAVUTIL_MEM_H)
|
||||
#include <libavutil/mem.h>
|
||||
#else
|
||||
#include <ffmpeg/mem.h>
|
||||
#endif
|
||||
#else
|
||||
#include "libavutil/avutil.h"
|
||||
#include "libavutil/crc.h"
|
||||
#include "libavutil/opt.h"
|
||||
#include "libavutil/mem.h"
|
||||
#include "libavutil/fifo.h"
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef __GNUC__
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
// calback used for logging
|
||||
//void ff_avutil_log(void* ptr, int level, const char* format, va_list va);
|
||||
|
||||
class DllAvUtilInterface
|
||||
{
|
||||
public:
|
||||
virtual ~DllAvUtilInterface() {}
|
||||
virtual void av_log_set_callback(void (*)(void*, int, const char*, va_list))=0;
|
||||
virtual void *av_malloc(unsigned int size)=0;
|
||||
virtual void *av_mallocz(unsigned int size)=0;
|
||||
virtual void *av_realloc(void *ptr, unsigned int size)=0;
|
||||
virtual void av_free(void *ptr)=0;
|
||||
virtual void av_freep(void *ptr)=0;
|
||||
virtual int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding)=0;
|
||||
virtual int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)=0;
|
||||
virtual const AVCRC* av_crc_get_table(AVCRCId crc_id)=0;
|
||||
virtual uint32_t av_crc(const AVCRC *ctx, uint32_t crc, const uint8_t *buffer, size_t length)=0;
|
||||
virtual int av_set_string3(void *obj, const char *name, const char *val, int alloc, const AVOption **o_out)=0;
|
||||
virtual AVFifoBuffer *av_fifo_alloc(unsigned int size) = 0;
|
||||
virtual void av_fifo_free(AVFifoBuffer *f) = 0;
|
||||
virtual void av_fifo_reset(AVFifoBuffer *f) = 0;
|
||||
virtual int av_fifo_size(AVFifoBuffer *f) = 0;
|
||||
virtual int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int)) = 0;
|
||||
virtual int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int (*func)(void*, void*, int)) = 0;
|
||||
virtual char *av_strdup(const char *s)=0;
|
||||
virtual void av_log_set_level(int level) = 0;
|
||||
};
|
||||
|
||||
#if (defined USE_EXTERNAL_FFMPEG)
|
||||
|
||||
// Use direct layer
|
||||
class DllAvUtilBase : public DllDynamic, DllAvUtilInterface
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~DllAvUtilBase() {}
|
||||
virtual void av_log_set_callback(void (*foo)(void*, int, const char*, va_list)) { ::av_log_set_callback(foo); }
|
||||
virtual void *av_malloc(unsigned int size) { return ::av_malloc(size); }
|
||||
virtual void *av_mallocz(unsigned int size) { return ::av_mallocz(size); }
|
||||
virtual void *av_realloc(void *ptr, unsigned int size) { return ::av_realloc(ptr, size); }
|
||||
virtual void av_free(void *ptr) { ::av_free(ptr); }
|
||||
virtual void av_freep(void *ptr) { ::av_freep(ptr); }
|
||||
virtual int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding d) { return ::av_rescale_rnd(a, b, c, d); }
|
||||
virtual int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) { return ::av_rescale_q(a, bq, cq); }
|
||||
virtual const AVCRC* av_crc_get_table(AVCRCId crc_id) { return ::av_crc_get_table(crc_id); }
|
||||
virtual uint32_t av_crc(const AVCRC *ctx, uint32_t crc, const uint8_t *buffer, size_t length) { return ::av_crc(ctx, crc, buffer, length); }
|
||||
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52,7,0)
|
||||
// API added on: 2008-12-16
|
||||
virtual int av_set_string3(void *obj, const char *name, const char *val, int alloc, const AVOption **o_out) { return ::av_set_string3(obj, name, val, alloc, o_out); }
|
||||
#else
|
||||
virtual int av_set_string3(void *obj, const char *name, const char *val, int alloc, const AVOption **o_out) { return AVERROR(ENOENT); }
|
||||
#endif
|
||||
virtual AVFifoBuffer *av_fifo_alloc(unsigned int size) {return ::av_fifo_alloc(size); }
|
||||
virtual void av_fifo_free(AVFifoBuffer *f) { ::av_fifo_free(f); }
|
||||
virtual void av_fifo_reset(AVFifoBuffer *f) { ::av_fifo_reset(f); }
|
||||
virtual int av_fifo_size(AVFifoBuffer *f) { return ::av_fifo_size(f); }
|
||||
virtual int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int))
|
||||
{ return ::av_fifo_generic_read(f, dest, buf_size, func); }
|
||||
virtual int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int (*func)(void*, void*, int))
|
||||
{ return ::av_fifo_generic_write(f, src, size, func); }
|
||||
virtual char *av_strdup(const char *s) { return ::av_strdup(s); }
|
||||
virtual void av_log_set_level(int level) { ::av_log_set_level(level); };
|
||||
|
||||
// DLL faking.
|
||||
virtual bool ResolveExports() { return true; }
|
||||
virtual bool Load() {
|
||||
CLog::Log(LOGDEBUG, "DllAvUtilBase: Using libavutil system library");
|
||||
return true;
|
||||
}
|
||||
virtual void Unload() {}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
class DllAvUtilBase : public DllDynamic, DllAvUtilInterface
|
||||
{
|
||||
DECLARE_DLL_WRAPPER(DllAvUtilBase, DLL_PATH_LIBAVUTIL)
|
||||
|
||||
LOAD_SYMBOLS()
|
||||
|
||||
DEFINE_METHOD1(void, av_log_set_callback, (void (*p1)(void*, int, const char*, va_list)))
|
||||
DEFINE_METHOD1(void*, av_malloc, (unsigned int p1))
|
||||
DEFINE_METHOD1(void*, av_mallocz, (unsigned int p1))
|
||||
DEFINE_METHOD2(void*, av_realloc, (void *p1, unsigned int p2))
|
||||
DEFINE_METHOD1(void, av_free, (void *p1))
|
||||
DEFINE_METHOD1(void, av_freep, (void *p1))
|
||||
DEFINE_METHOD4(int64_t, av_rescale_rnd, (int64_t p1, int64_t p2, int64_t p3, enum AVRounding p4));
|
||||
DEFINE_METHOD3(int64_t, av_rescale_q, (int64_t p1, AVRational p2, AVRational p3));
|
||||
DEFINE_METHOD1(const AVCRC*, av_crc_get_table, (AVCRCId p1))
|
||||
DEFINE_METHOD4(uint32_t, av_crc, (const AVCRC *p1, uint32_t p2, const uint8_t *p3, size_t p4));
|
||||
DEFINE_METHOD5(int, av_set_string3, (void *p1, const char *p2, const char *p3, int p4, const AVOption **p5));
|
||||
DEFINE_METHOD1(AVFifoBuffer*, av_fifo_alloc, (unsigned int p1))
|
||||
DEFINE_METHOD1(void, av_fifo_free, (AVFifoBuffer *p1))
|
||||
DEFINE_METHOD1(void, av_fifo_reset, (AVFifoBuffer *p1))
|
||||
DEFINE_METHOD1(int, av_fifo_size, (AVFifoBuffer *p1))
|
||||
DEFINE_METHOD4(int, av_fifo_generic_read, (AVFifoBuffer *p1, void *p2, int p3, void (*p4)(void*, void*, int)))
|
||||
DEFINE_METHOD4(int, av_fifo_generic_write, (AVFifoBuffer *p1, void *p2, int p3, int (*p4)(void*, void*, int)))
|
||||
DEFINE_METHOD1(char*, av_strdup, (const char *p1))
|
||||
DEFINE_METHOD1(void, av_log_set_level, (int p1))
|
||||
|
||||
public:
|
||||
BEGIN_METHOD_RESOLVE()
|
||||
RESOLVE_METHOD(av_log_set_callback)
|
||||
RESOLVE_METHOD(av_malloc)
|
||||
RESOLVE_METHOD(av_mallocz)
|
||||
RESOLVE_METHOD(av_realloc)
|
||||
RESOLVE_METHOD(av_free)
|
||||
RESOLVE_METHOD(av_freep)
|
||||
RESOLVE_METHOD(av_rescale_rnd)
|
||||
RESOLVE_METHOD(av_rescale_q)
|
||||
RESOLVE_METHOD(av_crc_get_table)
|
||||
RESOLVE_METHOD(av_crc)
|
||||
RESOLVE_METHOD(av_set_string3)
|
||||
RESOLVE_METHOD(av_fifo_alloc)
|
||||
RESOLVE_METHOD(av_fifo_free)
|
||||
RESOLVE_METHOD(av_fifo_reset)
|
||||
RESOLVE_METHOD(av_fifo_size)
|
||||
RESOLVE_METHOD(av_fifo_generic_read)
|
||||
RESOLVE_METHOD(av_fifo_generic_write)
|
||||
RESOLVE_METHOD(av_strdup)
|
||||
END_METHOD_RESOLVE()
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
class DllAvUtil : public DllAvUtilBase
|
||||
{
|
||||
public:
|
||||
virtual bool Load()
|
||||
{
|
||||
if( DllAvUtilBase::Load() )
|
||||
{
|
||||
//DllAvUtilBase::av_log_set_callback(ff_avutil_log);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
245
DllBCM.h
Normal file
245
DllBCM.h
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
#pragma once
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(HAVE_PLATFORM_RASPBERRY_PI)
|
||||
|
||||
#if (defined HAVE_CONFIG_H) && (!defined WIN32)
|
||||
#include "config.h"
|
||||
#endif
|
||||
#ifndef __GNUC__
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4244)
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include <bcm_host.h>
|
||||
}
|
||||
|
||||
#include "DynamicDll.h"
|
||||
#include "utils/log.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class DllBcmHostDisplayInterface
|
||||
{
|
||||
public:
|
||||
virtual ~DllBcmHostDisplayInterface() {}
|
||||
|
||||
virtual DISPMANX_DISPLAY_HANDLE_T vc_dispmanx_display_open( uint32_t device ) = 0;
|
||||
virtual DISPMANX_UPDATE_HANDLE_T vc_dispmanx_update_start( int32_t priority ) = 0;
|
||||
virtual DISPMANX_ELEMENT_HANDLE_T vc_dispmanx_element_add ( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_DISPLAY_HANDLE_T display,
|
||||
int32_t layer, const VC_RECT_T *dest_rect, DISPMANX_RESOURCE_HANDLE_T src,
|
||||
const VC_RECT_T *src_rect, DISPMANX_PROTECTION_T protection,
|
||||
VC_DISPMANX_ALPHA_T *alpha,
|
||||
DISPMANX_CLAMP_T *clamp, DISPMANX_TRANSFORM_T transform ) = 0;
|
||||
virtual int vc_dispmanx_update_submit_sync( DISPMANX_UPDATE_HANDLE_T update ) = 0;
|
||||
virtual int vc_dispmanx_element_remove( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_ELEMENT_HANDLE_T element ) = 0;
|
||||
virtual int vc_dispmanx_display_close( DISPMANX_DISPLAY_HANDLE_T display ) = 0;
|
||||
virtual int vc_dispmanx_display_get_info( DISPMANX_DISPLAY_HANDLE_T display, DISPMANX_MODEINFO_T * pinfo ) = 0;
|
||||
virtual int vc_dispmanx_display_set_background( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_DISPLAY_HANDLE_T display,
|
||||
uint8_t red, uint8_t green, uint8_t blue ) = 0;
|
||||
};
|
||||
|
||||
#if (defined USE_EXTERNAL_LIBBCM_HOST)
|
||||
class DllBcmHostDisplay : public DllDynamic, DllBcmHostDisplayInterface
|
||||
{
|
||||
public:
|
||||
virtual DISPMANX_DISPLAY_HANDLE_T vc_dispmanx_display_open( uint32_t device )
|
||||
{ return ::vc_dispmanx_display_open(device); };
|
||||
virtual DISPMANX_UPDATE_HANDLE_T vc_dispmanx_update_start( int32_t priority )
|
||||
{ return ::vc_dispmanx_update_start(priority); };
|
||||
virtual DISPMANX_ELEMENT_HANDLE_T vc_dispmanx_element_add ( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_DISPLAY_HANDLE_T display,
|
||||
int32_t layer, const VC_RECT_T *dest_rect, DISPMANX_RESOURCE_HANDLE_T src,
|
||||
const VC_RECT_T *src_rect, DISPMANX_PROTECTION_T protection,
|
||||
VC_DISPMANX_ALPHA_T *alpha,
|
||||
DISPMANX_CLAMP_T *clamp, DISPMANX_TRANSFORM_T transform )
|
||||
{ return ::vc_dispmanx_element_add(update, display, layer, dest_rect, src, src_rect, protection, alpha, clamp, transform); };
|
||||
virtual int vc_dispmanx_update_submit_sync( DISPMANX_UPDATE_HANDLE_T update )
|
||||
{ return ::vc_dispmanx_update_submit_sync(update); };
|
||||
virtual int vc_dispmanx_element_remove( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_ELEMENT_HANDLE_T element )
|
||||
{ return ::vc_dispmanx_element_remove(update, element); };
|
||||
virtual int vc_dispmanx_display_close( DISPMANX_DISPLAY_HANDLE_T display )
|
||||
{ return ::vc_dispmanx_display_close(display); };
|
||||
virtual int vc_dispmanx_display_get_info( DISPMANX_DISPLAY_HANDLE_T display, DISPMANX_MODEINFO_T *pinfo )
|
||||
{ return ::vc_dispmanx_display_get_info(display, pinfo); };
|
||||
virtual int vc_dispmanx_display_set_background( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_DISPLAY_HANDLE_T display,
|
||||
uint8_t red, uint8_t green, uint8_t blue )
|
||||
{ return ::vc_dispmanx_display_set_background(update, display, red, green, blue); };
|
||||
virtual bool ResolveExports()
|
||||
{ return true; }
|
||||
virtual bool Load()
|
||||
{
|
||||
CLog::Log(LOGDEBUG, "DllBcm: Using omx system library");
|
||||
return true;
|
||||
}
|
||||
virtual void Unload() {}
|
||||
};
|
||||
#else
|
||||
class DllBcmHostDisplay : public DllDynamic, DllBcmHostDisplayInterface
|
||||
{
|
||||
//DECLARE_DLL_WRAPPER(DllBcmHostDisplay, "/opt/vc/lib/libopenmaxil.so")
|
||||
DECLARE_DLL_WRAPPER(DllBcmHostDisplay, "/opt/vc/lib/libEGL.so")
|
||||
|
||||
DEFINE_METHOD1(DISPMANX_DISPLAY_HANDLE_T, vc_dispmanx_display_open, (uint32_t p1 ))
|
||||
DEFINE_METHOD1(DISPMANX_UPDATE_HANDLE_T, vc_dispmanx_update_start, (int32_t p1 ))
|
||||
DEFINE_METHOD10(DISPMANX_ELEMENT_HANDLE_T, vc_dispmanx_element_add, (DISPMANX_UPDATE_HANDLE_T p1, DISPMANX_DISPLAY_HANDLE_T p2,
|
||||
int32_t p3, const VC_RECT_T *p4, DISPMANX_RESOURCE_HANDLE_T p5,
|
||||
const VC_RECT_T *p6, DISPMANX_PROTECTION_T p7,
|
||||
VC_DISPMANX_ALPHA_T *p8,
|
||||
DISPMANX_CLAMP_T *p9, DISPMANX_TRANSFORM_T p10 ))
|
||||
DEFINE_METHOD1(int, vc_dispmanx_update_submit_sync, (DISPMANX_UPDATE_HANDLE_T p1))
|
||||
DEFINE_METHOD2(int, vc_dispmanx_element_remove, (DISPMANX_UPDATE_HANDLE_T p1, DISPMANX_ELEMENT_HANDLE_T p2))
|
||||
DEFINE_METHOD1(int, vc_dispmanx_display_close, (DISPMANX_DISPLAY_HANDLE_T p1))
|
||||
DEFINE_METHOD2(int, vc_dispmanx_display_get_info, (DISPMANX_DISPLAY_HANDLE_T p1, DISPMANX_MODEINFO_T *p2))
|
||||
DEFINE_METHOD5(int, vc_dispmanx_display_set_background, ( DISPMANX_UPDATE_HANDLE_T p1, DISPMANX_DISPLAY_HANDLE_T p2,
|
||||
uint8_t p3, uint8_t p4, uint8_t p5 ))
|
||||
BEGIN_METHOD_RESOLVE()
|
||||
RESOLVE_METHOD(vc_dispmanx_display_open)
|
||||
RESOLVE_METHOD(vc_dispmanx_update_start)
|
||||
RESOLVE_METHOD(vc_dispmanx_element_add)
|
||||
RESOLVE_METHOD(vc_dispmanx_update_submit_sync)
|
||||
RESOLVE_METHOD(vc_dispmanx_element_remove)
|
||||
RESOLVE_METHOD(vc_dispmanx_display_close)
|
||||
RESOLVE_METHOD(vc_dispmanx_display_get_info)
|
||||
RESOLVE_METHOD(vc_dispmanx_display_set_background)
|
||||
END_METHOD_RESOLVE()
|
||||
|
||||
public:
|
||||
virtual bool Load()
|
||||
{
|
||||
return DllDynamic::Load();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
class DllBcmHostInterface
|
||||
{
|
||||
public:
|
||||
virtual ~DllBcmHostInterface() {}
|
||||
|
||||
virtual void bcm_host_init() = 0;
|
||||
virtual void bcm_host_deinit() = 0;
|
||||
virtual int32_t graphics_get_display_size( const uint16_t display_number, uint32_t *width, uint32_t *height) = 0;
|
||||
virtual int vc_tv_hdmi_power_on_best(uint32_t width, uint32_t height, uint32_t frame_rate,
|
||||
HDMI_INTERLACED_T scan_mode, EDID_MODE_MATCH_FLAG_T match_flags) = 0;
|
||||
virtual int vc_tv_hdmi_power_on_best_3d(uint32_t width, uint32_t height, uint32_t frame_rate,
|
||||
HDMI_INTERLACED_T scan_mode, EDID_MODE_MATCH_FLAG_T match_flags) = 0;
|
||||
|
||||
virtual int vc_tv_hdmi_get_supported_modes(HDMI_RES_GROUP_T group, TV_SUPPORTED_MODE_T *supported_modes,
|
||||
uint32_t max_supported_modes, HDMI_RES_GROUP_T *preferred_group,
|
||||
uint32_t *preferred_mode) = 0;
|
||||
virtual int vc_tv_hdmi_power_on_explicit(HDMI_MODE_T mode, HDMI_RES_GROUP_T group, uint32_t code) = 0;
|
||||
virtual int vc_tv_get_state(TV_GET_STATE_RESP_T *tvstate) = 0;
|
||||
virtual void vc_tv_register_callback(TVSERVICE_CALLBACK_T callback, void *callback_data) = 0;
|
||||
virtual void vc_tv_unregister_callback(TVSERVICE_CALLBACK_T callback) = 0;
|
||||
virtual void vc_cec_register_callback(CECSERVICE_CALLBACK_T callback, void *callback_data) = 0;
|
||||
//virtual void vc_cec_unregister_callback(CECSERVICE_CALLBACK_T callback) = 0;
|
||||
};
|
||||
|
||||
#if (defined USE_EXTERNAL_LIBBCM_HOST)
|
||||
class DllBcmHost : public DllDynamic, DllBcmHostInterface
|
||||
{
|
||||
public:
|
||||
virtual void bcm_host_init()
|
||||
{ return ::bcm_host_init(); };
|
||||
virtual void bcm_host_deinit()
|
||||
{ return ::bcm_host_deinit(); };
|
||||
virtual int32_t graphics_get_display_size( const uint16_t display_number, uint32_t *width, uint32_t *height)
|
||||
{ return ::graphics_get_display_size(display_number, width, height); };
|
||||
virtual int vc_tv_hdmi_power_on_best(uint32_t width, uint32_t height, uint32_t frame_rate,
|
||||
HDMI_INTERLACED_T scan_mode, EDID_MODE_MATCH_FLAG_T match_flags)
|
||||
{ return ::vc_tv_hdmi_power_on_best(width, height, frame_rate, scan_mode, match_flags); };
|
||||
virtual int vc_tv_hdmi_power_on_best_3d(uint32_t width, uint32_t height, uint32_t frame_rate,
|
||||
HDMI_INTERLACED_T scan_mode, EDID_MODE_MATCH_FLAG_T match_flags)
|
||||
{ return ::vc_tv_hdmi_power_on_best_3d(width, height, frame_rate, scan_mode, match_flags); };
|
||||
virtual int vc_tv_hdmi_get_supported_modes(HDMI_RES_GROUP_T group, TV_SUPPORTED_MODE_T *supported_modes,
|
||||
uint32_t max_supported_modes, HDMI_RES_GROUP_T *preferred_group,
|
||||
uint32_t *preferred_mode)
|
||||
{ return ::vc_tv_hdmi_get_supported_modes(group, supported_modes, max_supported_modes, preferred_group, preferred_mode); };
|
||||
virtual int vc_tv_hdmi_power_on_explicit(HDMI_MODE_T mode, HDMI_RES_GROUP_T group, uint32_t code)
|
||||
{ return ::vc_tv_hdmi_power_on_explicit(mode, group, code); };
|
||||
virtual int vc_tv_get_state(TV_GET_STATE_RESP_T *tvstate)
|
||||
{ return ::vc_tv_get_state(tvstate); };
|
||||
virtual void vc_tv_register_callback(TVSERVICE_CALLBACK_T callback, void *callback_data)
|
||||
{ ::vc_tv_register_callback(callback, callback_data); };
|
||||
virtual void vc_tv_unregister_callback(TVSERVICE_CALLBACK_T callback)
|
||||
{ ::vc_tv_unregister_callback(callback); };
|
||||
virtual void vc_cec_register_callback(CECSERVICE_CALLBACK_T callback, void *callback_data)
|
||||
{ ::vc_cec_register_callback(callback, callback_data); };
|
||||
//virtual void vc_cec_unregister_callback(CECSERVICE_CALLBACK_T callback)
|
||||
// { ::vc_cec_unregister_callback(callback); };
|
||||
virtual bool ResolveExports()
|
||||
{ return true; }
|
||||
virtual bool Load()
|
||||
{
|
||||
CLog::Log(LOGDEBUG, "DllBcm: Using omx system library");
|
||||
return true;
|
||||
}
|
||||
virtual void Unload() {}
|
||||
};
|
||||
#else
|
||||
class DllBcmHost : public DllDynamic, DllBcmHostInterface
|
||||
{
|
||||
DECLARE_DLL_WRAPPER(DllBcmHost, "/opt/vc/lib/libbcm_host.so")
|
||||
|
||||
DEFINE_METHOD0(void, bcm_host_init)
|
||||
DEFINE_METHOD0(void, bcm_host_deinit)
|
||||
DEFINE_METHOD3(int32_t, graphics_get_display_size, (const uint16_t p1, uint32_t *p2, uint32_t *p3))
|
||||
DEFINE_METHOD5(int, vc_tv_hdmi_power_on_best, (uint32_t p1, uint32_t p2, uint32_t p3,
|
||||
HDMI_INTERLACED_T p4, EDID_MODE_MATCH_FLAG_T p5))
|
||||
DEFINE_METHOD5(int, vc_tv_hdmi_power_on_best_3d, (uint32_t p1, uint32_t p2, uint32_t p3,
|
||||
HDMI_INTERLACED_T p4, EDID_MODE_MATCH_FLAG_T p5))
|
||||
DEFINE_METHOD5(int, vc_tv_hdmi_get_supported_modes, (HDMI_RES_GROUP_T p1, TV_SUPPORTED_MODE_T *p2,
|
||||
uint32_t p3, HDMI_RES_GROUP_T *p4, uint32_t *p5))
|
||||
DEFINE_METHOD3(int, vc_tv_hdmi_power_on_explicit, (HDMI_MODE_T p1, HDMI_RES_GROUP_T p2, uint32_t p3))
|
||||
DEFINE_METHOD1(int, vc_tv_get_state, (TV_GET_STATE_RESP_T *p1))
|
||||
|
||||
DEFINE_METHOD2(void, vc_tv_register_callback, (TVSERVICE_CALLBACK_T p1, void *p2))
|
||||
DEFINE_METHOD1(void, vc_tv_unregister_callback, (TVSERVICE_CALLBACK_T p1))
|
||||
|
||||
DEFINE_METHOD2(void, vc_cec_register_callback, (CECSERVICE_CALLBACK_T p1, void *p2))
|
||||
//DEFINE_METHOD1(void, vc_cec_unregister_callback, (CECSERVICE_CALLBACK_T p1))
|
||||
|
||||
BEGIN_METHOD_RESOLVE()
|
||||
RESOLVE_METHOD(bcm_host_init)
|
||||
RESOLVE_METHOD(bcm_host_deinit)
|
||||
RESOLVE_METHOD(graphics_get_display_size)
|
||||
RESOLVE_METHOD(vc_tv_hdmi_power_on_best)
|
||||
RESOLVE_METHOD(vc_tv_hdmi_power_on_best_3d)
|
||||
RESOLVE_METHOD(vc_tv_hdmi_get_supported_modes)
|
||||
RESOLVE_METHOD(vc_tv_hdmi_power_on_explicit)
|
||||
RESOLVE_METHOD(vc_tv_get_state)
|
||||
RESOLVE_METHOD(vc_tv_register_callback)
|
||||
RESOLVE_METHOD(vc_tv_unregister_callback)
|
||||
RESOLVE_METHOD(vc_cec_register_callback)
|
||||
//RESOLVE_METHOD(vc_cec_unregister_callback)
|
||||
END_METHOD_RESOLVE()
|
||||
|
||||
public:
|
||||
virtual bool Load()
|
||||
{
|
||||
return DllDynamic::Load();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
123
DllOMX.h
Normal file
123
DllOMX.h
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
#pragma once
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(HAVE_OMXLIB)
|
||||
|
||||
#if (defined HAVE_CONFIG_H) && (!defined WIN32)
|
||||
#include "config.h"
|
||||
#endif
|
||||
#ifndef __GNUC__
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4244)
|
||||
#endif
|
||||
|
||||
#include "DynamicDll.h"
|
||||
#include "utils/log.h"
|
||||
|
||||
#include <IL/OMX_Core.h>
|
||||
#include <IL/OMX_Component.h>
|
||||
#include <IL/OMX_Index.h>
|
||||
#include <IL/OMX_Image.h>
|
||||
#include <IL/OMX_Video.h>
|
||||
#include <IL/OMX_Broadcom.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class DllOMXInterface
|
||||
{
|
||||
public:
|
||||
virtual ~DllOMXInterface() {}
|
||||
|
||||
virtual OMX_ERRORTYPE OMX_Init(void) = 0;
|
||||
virtual OMX_ERRORTYPE OMX_Deinit(void) = 0;
|
||||
virtual OMX_ERRORTYPE OMX_GetHandle(OMX_HANDLETYPE *pHandle, OMX_STRING cComponentName, OMX_PTR pAppData, OMX_CALLBACKTYPE *pCallBacks) = 0;
|
||||
virtual OMX_ERRORTYPE OMX_FreeHandle(OMX_HANDLETYPE hComponent) = 0;
|
||||
virtual OMX_ERRORTYPE OMX_GetComponentsOfRole(OMX_STRING role, OMX_U32 *pNumComps, OMX_U8 **compNames) = 0;
|
||||
virtual OMX_ERRORTYPE OMX_GetRolesOfComponent(OMX_STRING compName, OMX_U32 *pNumRoles, OMX_U8 **roles) = 0;
|
||||
virtual OMX_ERRORTYPE OMX_ComponentNameEnum(OMX_STRING cComponentName, OMX_U32 nNameLength, OMX_U32 nIndex) = 0;
|
||||
virtual OMX_ERRORTYPE OMX_SetupTunnel(OMX_HANDLETYPE hOutput, OMX_U32 nPortOutput, OMX_HANDLETYPE hInput, OMX_U32 nPortInput) = 0;
|
||||
|
||||
};
|
||||
|
||||
#if (defined USE_EXTERNAL_OMX)
|
||||
class DllOMX : public DllDynamic, DllOMXInterface
|
||||
{
|
||||
public:
|
||||
virtual OMX_ERRORTYPE OMX_Init(void)
|
||||
{ return ::OMX_Init(); };
|
||||
virtual OMX_ERRORTYPE OMX_Deinit(void)
|
||||
{ return ::OMX_Deinit(); };
|
||||
virtual OMX_ERRORTYPE OMX_GetHandle(OMX_HANDLETYPE *pHandle, OMX_STRING cComponentName, OMX_PTR pAppData, OMX_CALLBACKTYPE *pCallBacks)
|
||||
{ return ::OMX_GetHandle(pHandle, cComponentName, pAppData, pCallBacks); };
|
||||
virtual OMX_ERRORTYPE OMX_FreeHandle(OMX_HANDLETYPE hComponent)
|
||||
{ return ::OMX_FreeHandle(hComponent); };
|
||||
virtual OMX_ERRORTYPE OMX_GetComponentsOfRole(OMX_STRING role, OMX_U32 *pNumComps, OMX_U8 **compNames)
|
||||
{ return ::OMX_GetComponentsOfRole(role, pNumComps, compNames); };
|
||||
virtual OMX_ERRORTYPE OMX_GetRolesOfComponent(OMX_STRING compName, OMX_U32 *pNumRoles, OMX_U8 **roles)
|
||||
{ return ::OMX_GetRolesOfComponent(compName, pNumRoles, roles); };
|
||||
virtual OMX_ERRORTYPE OMX_ComponentNameEnum(OMX_STRING cComponentName, OMX_U32 nNameLength, OMX_U32 nIndex)
|
||||
{ return ::OMX_ComponentNameEnum(cComponentName, nNameLength, nIndex); };
|
||||
virtual OMX_ERRORTYPE OMX_SetupTunnel(OMX_HANDLETYPE hOutput, OMX_U32 nPortOutput, OMX_HANDLETYPE hInput, OMX_U32 nPortInput)
|
||||
{ return ::OMX_SetupTunnel(hOutput, nPortOutput, hInput, nPortInput); };
|
||||
virtual bool ResolveExports()
|
||||
{ return true; }
|
||||
virtual bool Load()
|
||||
{
|
||||
CLog::Log(LOGDEBUG, "DllOMX: Using omx system library");
|
||||
return true;
|
||||
}
|
||||
virtual void Unload() {}
|
||||
};
|
||||
#else
|
||||
class DllOMX : public DllDynamic, DllOMXInterface
|
||||
{
|
||||
//DECLARE_DLL_WRAPPER(DllLibOpenMax, "/usr/lib/libnvomx.so")
|
||||
DECLARE_DLL_WRAPPER(DllOMX, "/opt/vc/lib/libopenmaxil.so")
|
||||
|
||||
DEFINE_METHOD0(OMX_ERRORTYPE, OMX_Init)
|
||||
DEFINE_METHOD0(OMX_ERRORTYPE, OMX_Deinit)
|
||||
DEFINE_METHOD4(OMX_ERRORTYPE, OMX_GetHandle, (OMX_HANDLETYPE *p1, OMX_STRING p2, OMX_PTR p3, OMX_CALLBACKTYPE *p4))
|
||||
DEFINE_METHOD1(OMX_ERRORTYPE, OMX_FreeHandle, (OMX_HANDLETYPE p1))
|
||||
DEFINE_METHOD3(OMX_ERRORTYPE, OMX_GetComponentsOfRole, (OMX_STRING p1, OMX_U32 *p2, OMX_U8 **p3))
|
||||
DEFINE_METHOD3(OMX_ERRORTYPE, OMX_GetRolesOfComponent, (OMX_STRING p1, OMX_U32 *p2, OMX_U8 **p3))
|
||||
DEFINE_METHOD3(OMX_ERRORTYPE, OMX_ComponentNameEnum, (OMX_STRING p1, OMX_U32 p2, OMX_U32 p3))
|
||||
DEFINE_METHOD4(OMX_ERRORTYPE, OMX_SetupTunnel, (OMX_HANDLETYPE p1, OMX_U32 p2, OMX_HANDLETYPE p3, OMX_U32 p4));
|
||||
BEGIN_METHOD_RESOLVE()
|
||||
RESOLVE_METHOD(OMX_Init)
|
||||
RESOLVE_METHOD(OMX_Deinit)
|
||||
RESOLVE_METHOD(OMX_GetHandle)
|
||||
RESOLVE_METHOD(OMX_FreeHandle)
|
||||
RESOLVE_METHOD(OMX_GetComponentsOfRole)
|
||||
RESOLVE_METHOD(OMX_GetRolesOfComponent)
|
||||
RESOLVE_METHOD(OMX_ComponentNameEnum)
|
||||
RESOLVE_METHOD(OMX_SetupTunnel)
|
||||
END_METHOD_RESOLVE()
|
||||
|
||||
public:
|
||||
virtual bool Load()
|
||||
{
|
||||
return DllDynamic::Load();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
95
DynamicDll.cpp
Normal file
95
DynamicDll.cpp
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "DynamicDll.h"
|
||||
#include "utils/log.h"
|
||||
|
||||
DllDynamic::DllDynamic()
|
||||
{
|
||||
m_dll=NULL;
|
||||
m_DelayUnload=true;
|
||||
}
|
||||
|
||||
DllDynamic::DllDynamic(const CStdString& strDllName)
|
||||
{
|
||||
m_strDllName=strDllName;
|
||||
m_dll=NULL;
|
||||
m_DelayUnload=true;
|
||||
}
|
||||
|
||||
DllDynamic::~DllDynamic()
|
||||
{
|
||||
Unload();
|
||||
}
|
||||
|
||||
bool DllDynamic::Load()
|
||||
{
|
||||
if (m_dll)
|
||||
return true;
|
||||
|
||||
/*
|
||||
if (!(m_dll=CSectionLoader::LoadDLL(m_strDllName, m_DelayUnload, LoadSymbols())))
|
||||
return false;
|
||||
|
||||
if (!ResolveExports())
|
||||
{
|
||||
CLog::Log(LOGERROR, "Unable to resolve exports from dll %s", m_strDllName.c_str());
|
||||
Unload();
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DllDynamic::Unload()
|
||||
{
|
||||
/*
|
||||
if(m_dll)
|
||||
CSectionLoader::UnloadDLL(m_strDllName);
|
||||
*/
|
||||
m_dll=NULL;
|
||||
}
|
||||
|
||||
bool DllDynamic::CanLoad()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DllDynamic::EnableDelayedUnload(bool bOnOff)
|
||||
{
|
||||
if (m_dll)
|
||||
return false;
|
||||
|
||||
m_DelayUnload=bOnOff;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DllDynamic::SetFile(const CStdString& strDllName)
|
||||
{
|
||||
if (m_dll)
|
||||
return false;
|
||||
|
||||
m_strDllName=strDllName;
|
||||
return true;
|
||||
}
|
||||
|
||||
497
DynamicDll.h
Normal file
497
DynamicDll.h
Normal file
|
|
@ -0,0 +1,497 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "utils/StdString.h"
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
//
|
||||
// DECLARE_DLL_WRAPPER
|
||||
//
|
||||
// Declares the constructor of the wrapper class.
|
||||
// This must be followed by one or more
|
||||
// DEFINE_METHODX/DEFINE_METHOD_LINKAGEX and
|
||||
// one BEGIN_METHOD_RESOLVE/END_METHOD_RESOLVE block.
|
||||
//
|
||||
// classname: name of the wrapper class to construct
|
||||
// dllname: file including path of the dll to wrap
|
||||
|
||||
#define DECLARE_DLL_WRAPPER(classname, dllname) \
|
||||
XDECLARE_DLL_WRAPPER(classname,dllname)
|
||||
|
||||
#define XDECLARE_DLL_WRAPPER(classname, dllname) \
|
||||
public: \
|
||||
classname () : DllDynamic( dllname ) {}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
//
|
||||
// DECLARE_DLL_WRAPPER_TEMPLATE_BEGIN
|
||||
//
|
||||
// Declares the constructor of the wrapper class.
|
||||
// The method SetFile(strDllName) can be used to set the
|
||||
// dll of this wrapper.
|
||||
// This must be followed by one or more
|
||||
// DEFINE_METHODX/DEFINE_METHOD_LINKAGEX and
|
||||
// one BEGIN_METHOD_RESOLVE/END_METHOD_RESOLVE block.
|
||||
//
|
||||
// classname: name of the wrapper class to construct
|
||||
//
|
||||
#define DECLARE_DLL_WRAPPER_TEMPLATE(classname) \
|
||||
public: \
|
||||
classname () {} \
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
//
|
||||
// LOAD_SYMBOLS
|
||||
//
|
||||
// Tells the dllloader to load Debug symblos when possible
|
||||
#define LOAD_SYMBOLS() \
|
||||
protected: \
|
||||
virtual bool LoadSymbols() { return true; }
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
//
|
||||
// DEFINE_GLOBAL
|
||||
//
|
||||
// Defines a global for export from the dll as well as
|
||||
// a function for accessing it (Get_name).
|
||||
//
|
||||
// type: The variables type.
|
||||
// name: Name of the variable.
|
||||
//
|
||||
|
||||
#define DEFINE_GLOBAL_PTR(type, name) \
|
||||
protected: \
|
||||
union { \
|
||||
type* m_##name; \
|
||||
void* m_##name##_ptr; \
|
||||
}; \
|
||||
public: \
|
||||
virtual type* Get_##name (void) \
|
||||
{ \
|
||||
return m_##name; \
|
||||
}
|
||||
|
||||
#define DEFINE_GLOBAL(type, name) \
|
||||
protected: \
|
||||
union { \
|
||||
type* m_##name; \
|
||||
void* m_##name##_ptr; \
|
||||
}; \
|
||||
public: \
|
||||
virtual type Get_##name (void) \
|
||||
{ \
|
||||
return *m_##name; \
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
//
|
||||
// DEFINE_METHOD_LINKAGE
|
||||
//
|
||||
// Defines a function for an export from a dll, if the
|
||||
// calling convention is not __cdecl.
|
||||
// Use DEFINE_METHOD_LINKAGE for each function to be resolved.
|
||||
//
|
||||
// result: Result of the function
|
||||
// linkage: Calling convention of the function
|
||||
// name: Name of the function
|
||||
// args: Arguments of the function, enclosed in parentheses
|
||||
//
|
||||
#define DEFINE_METHOD_LINKAGE_FP(result, linkage, name, args) \
|
||||
protected: \
|
||||
typedef result (linkage * name##_METHOD) args; \
|
||||
public: \
|
||||
union { \
|
||||
name##_METHOD name; \
|
||||
void* name##_ptr; \
|
||||
};
|
||||
|
||||
#define DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, args2) \
|
||||
protected: \
|
||||
typedef result (linkage * name##_METHOD) args; \
|
||||
union { \
|
||||
name##_METHOD m_##name; \
|
||||
void* m_##name##_ptr; \
|
||||
}; \
|
||||
public: \
|
||||
virtual result name args \
|
||||
{ \
|
||||
return m_##name args2; \
|
||||
}
|
||||
|
||||
#define DEFINE_METHOD_LINKAGE0(result, linkage, name) \
|
||||
DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, () , ())
|
||||
|
||||
#define DEFINE_METHOD_LINKAGE1(result, linkage, name, args) \
|
||||
DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1))
|
||||
|
||||
#define DEFINE_METHOD_LINKAGE2(result, linkage, name, args) \
|
||||
DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2))
|
||||
|
||||
#define DEFINE_METHOD_LINKAGE3(result, linkage, name, args) \
|
||||
DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3))
|
||||
|
||||
#define DEFINE_METHOD_LINKAGE4(result, linkage, name, args) \
|
||||
DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4))
|
||||
|
||||
#define DEFINE_METHOD_LINKAGE5(result, linkage, name, args) \
|
||||
DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4, p5))
|
||||
|
||||
#define DEFINE_METHOD_LINKAGE6(result, linkage, name, args) \
|
||||
DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4, p5, p6))
|
||||
|
||||
#define DEFINE_METHOD_LINKAGE7(result, linkage, name, args) \
|
||||
DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4, p5, p6, p7))
|
||||
|
||||
#define DEFINE_METHOD_LINKAGE8(result, linkage, name, args) \
|
||||
DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4, p5, p6, p7, p8))
|
||||
|
||||
#define DEFINE_METHOD_LINKAGE9(result, linkage, name, args) \
|
||||
DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4, p5, p6, p7, p8, p9))
|
||||
|
||||
#define DEFINE_METHOD_LINKAGE10(result, linkage, name, args) \
|
||||
DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10))
|
||||
|
||||
#define DEFINE_METHOD_LINKAGE11(result, linkage, name, args) \
|
||||
DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11))
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
//
|
||||
// DEFINE_METHOD_FP
|
||||
//
|
||||
// Defines a function for an export from a dll as a fuction pointer.
|
||||
// Use DEFINE_METHOD_FP for each function to be resolved. Functions
|
||||
// defined like this are not listed by IntelliSence.
|
||||
//
|
||||
// result: Result of the function
|
||||
// name: Name of the function
|
||||
// args: Arguments of the function, enclosed in parentheses
|
||||
// The parameter names can be anything
|
||||
//
|
||||
#define DEFINE_METHOD_FP(result, name, args) DEFINE_METHOD_LINKAGE_FP(result, __cdecl, name, args)
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
//
|
||||
// DEFINE_METHODX
|
||||
//
|
||||
// Defines a function for an export from a dll.
|
||||
// Use DEFINE_METHODX for each function to be resolved.
|
||||
// where X is the number of parameter the function has.
|
||||
//
|
||||
// result: Result of the function
|
||||
// name: Name of the function
|
||||
// args: Arguments of the function, enclosed in parentheses
|
||||
// The parameter names have to be renamed to px, where
|
||||
// x is the number of the parameter
|
||||
//
|
||||
#define DEFINE_METHOD0(result, name) DEFINE_METHOD_LINKAGE0(result, __cdecl, name)
|
||||
#define DEFINE_METHOD1(result, name, args) DEFINE_METHOD_LINKAGE1(result, __cdecl, name, args)
|
||||
#define DEFINE_METHOD2(result, name, args) DEFINE_METHOD_LINKAGE2(result, __cdecl, name, args)
|
||||
#define DEFINE_METHOD3(result, name, args) DEFINE_METHOD_LINKAGE3(result, __cdecl, name, args)
|
||||
#define DEFINE_METHOD4(result, name, args) DEFINE_METHOD_LINKAGE4(result, __cdecl, name, args)
|
||||
#define DEFINE_METHOD5(result, name, args) DEFINE_METHOD_LINKAGE5(result, __cdecl, name, args)
|
||||
#define DEFINE_METHOD6(result, name, args) DEFINE_METHOD_LINKAGE6(result, __cdecl, name, args)
|
||||
#define DEFINE_METHOD7(result, name, args) DEFINE_METHOD_LINKAGE7(result, __cdecl, name, args)
|
||||
#define DEFINE_METHOD8(result, name, args) DEFINE_METHOD_LINKAGE8(result, __cdecl, name, args)
|
||||
#define DEFINE_METHOD9(result, name, args) DEFINE_METHOD_LINKAGE9(result, __cdecl, name, args)
|
||||
#define DEFINE_METHOD10(result, name, args) DEFINE_METHOD_LINKAGE10(result, __cdecl, name, args)
|
||||
#define DEFINE_METHOD11(result, name, args) DEFINE_METHOD_LINKAGE11(result, __cdecl, name, args)
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
//
|
||||
// DEFINE_FUNC_ALIGNED 0-X
|
||||
//
|
||||
// Defines a function for an export from a dll, wich
|
||||
// require a aligned stack on function call
|
||||
// Use DEFINE_FUNC_ALIGNED for each function to be resolved.
|
||||
//
|
||||
// result: Result of the function
|
||||
// linkage: Calling convention of the function
|
||||
// name: Name of the function
|
||||
// args: Argument types of the function
|
||||
//
|
||||
// Actual function call will expand to something like this
|
||||
// this will align the stack (esp) at the point of function
|
||||
// entry as required by gcc compiled dlls, it is abit abfuscated
|
||||
// to allow for different sized variables
|
||||
//
|
||||
// __int64 test(__int64 p1, char p2, char p3)
|
||||
// {
|
||||
// int o,s = ((sizeof(p1)+3)&~3)+((sizeof(p2)+3)&~3)+((sizeof(p3)+3)&~3);
|
||||
// __asm mov [o],esp;
|
||||
// __asm sub esp, [s];
|
||||
// __asm and esp, ~15;
|
||||
// __asm add esp, [s]
|
||||
// m_test(p1, p2, p3); //return value will still be correct aslong as we don't mess with it
|
||||
// __asm mov esp,[o];
|
||||
// };
|
||||
|
||||
#define ALS(a) ((sizeof(a)+3)&~3)
|
||||
#define DEFINE_FUNC_PART1(result, linkage, name, args) \
|
||||
private: \
|
||||
typedef result (linkage * name##_type)##args; \
|
||||
union { \
|
||||
name##_type m_##name; \
|
||||
void* m_##name##_ptr; \
|
||||
}; \
|
||||
public: \
|
||||
virtual result name##args
|
||||
|
||||
#define DEFINE_FUNC_PART2(size) \
|
||||
{ \
|
||||
int o,s = size; \
|
||||
__asm { \
|
||||
__asm mov [o], esp \
|
||||
__asm sub esp, [s] \
|
||||
__asm and esp, ~15 \
|
||||
__asm add esp, [s] \
|
||||
}
|
||||
|
||||
#define DEFINE_FUNC_PART3(name,args) \
|
||||
m_##name##args; \
|
||||
__asm { \
|
||||
__asm mov esp,[o] \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DEFINE_FUNC_ALIGNED0(result, linkage, name) \
|
||||
DEFINE_FUNC_PART1(result, linkage, name, ()) \
|
||||
DEFINE_FUNC_PART2(0) \
|
||||
DEFINE_FUNC_PART3(name,())
|
||||
|
||||
#define DEFINE_FUNC_ALIGNED1(result, linkage, name, t1) \
|
||||
DEFINE_FUNC_PART1(result, linkage, name, (t1 p1)) \
|
||||
DEFINE_FUNC_PART2(ALS(p1)) \
|
||||
DEFINE_FUNC_PART3(name,(p1))
|
||||
|
||||
#define DEFINE_FUNC_ALIGNED2(result, linkage, name, t1, t2) \
|
||||
DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2)) \
|
||||
DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)) \
|
||||
DEFINE_FUNC_PART3(name,(p1, p2))
|
||||
|
||||
#define DEFINE_FUNC_ALIGNED3(result, linkage, name, t1, t2, t3) \
|
||||
DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2, t3 p3)) \
|
||||
DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)+ALS(p3)) \
|
||||
DEFINE_FUNC_PART3(name,(p1, p2, p3))
|
||||
|
||||
#define DEFINE_FUNC_ALIGNED4(result, linkage, name, t1, t2, t3, t4) \
|
||||
DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4)) \
|
||||
DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)+ALS(p3)+ALS(p4)) \
|
||||
DEFINE_FUNC_PART3(name,(p1, p2, p3, p4))
|
||||
|
||||
#define DEFINE_FUNC_ALIGNED5(result, linkage, name, t1, t2, t3, t4, t5) \
|
||||
DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4, t5 p5)) \
|
||||
DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)+ALS(p3)+ALS(p4)+ALS(p5)) \
|
||||
DEFINE_FUNC_PART3(name,(p1, p2, p3, p4, p5))
|
||||
|
||||
#define DEFINE_FUNC_ALIGNED6(result, linkage, name, t1, t2, t3, t4, t5, t6) \
|
||||
DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6)) \
|
||||
DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)+ALS(p3)+ALS(p4)+ALS(p5)+ALS(p6)) \
|
||||
DEFINE_FUNC_PART3(name,(p1, p2, p3, p4, p5, p6))
|
||||
|
||||
#define DEFINE_FUNC_ALIGNED7(result, linkage, name, t1, t2, t3, t4, t5, t6, t7) \
|
||||
DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7)) \
|
||||
DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)+ALS(p3)+ALS(p4)+ALS(p5)+ALS(p6)+ALS(p7)) \
|
||||
DEFINE_FUNC_PART3(name,(p1, p2, p3, p4, p5, p6, p7))
|
||||
|
||||
#define DEFINE_FUNC_ALIGNED8(result, linkage, name, t1, t2, t3, t4, t5, t6, t7, t8) \
|
||||
DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8)) \
|
||||
DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)+ALS(p3)+ALS(p4)+ALS(p5)+ALS(p6)+ALS(p7)+ALS(p8)) \
|
||||
DEFINE_FUNC_PART3(name,(p1, p2, p3, p4, p5, p6, p7, p8))
|
||||
|
||||
#define DEFINE_FUNC_ALIGNED9(result, linkage, name, t1, t2, t3, t4, t5, t6, t7, t8, t9) \
|
||||
DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9)) \
|
||||
DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)+ALS(p3)+ALS(p4)+ALS(p5)+ALS(p6)+ALS(p7)+ALS(p8)+ALS(p9)) \
|
||||
DEFINE_FUNC_PART3(name,(p1, p2, p3, p4, p5, p6, p7, p8, p9))
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
//
|
||||
// BEGIN_METHOD_RESOLVE/END_METHOD_RESOLVE
|
||||
//
|
||||
// Defines a method that resolves the exported functions
|
||||
// defined with DEFINE_METHOD or DEFINE_METHOD_LINKAGE.
|
||||
// There must be a RESOLVE_METHOD or RESOLVE_METHOD_RENAME
|
||||
// for each DEFINE_METHOD or DEFINE_METHOD_LINKAGE within this
|
||||
// block. This block must be followed by an END_METHOD_RESOLVE.
|
||||
//
|
||||
#define BEGIN_METHOD_RESOLVE() \
|
||||
protected: \
|
||||
virtual bool ResolveExports() \
|
||||
{ \
|
||||
return (
|
||||
|
||||
#define END_METHOD_RESOLVE() \
|
||||
1 \
|
||||
); \
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
//
|
||||
// RESOLVE_METHOD
|
||||
//
|
||||
// Resolves a method from a dll
|
||||
//
|
||||
// method: Name of the method defined with DEFINE_METHOD
|
||||
// or DEFINE_METHOD_LINKAGE
|
||||
//
|
||||
#define RESOLVE_METHOD(method) \
|
||||
m_dll->ResolveExport( #method , & m_##method##_ptr ) &&
|
||||
|
||||
#define RESOLVE_METHOD_FP(method) \
|
||||
m_dll->ResolveExport( #method , & method##_ptr ) &&
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
//
|
||||
// RESOLVE_METHOD_RENAME
|
||||
//
|
||||
// Resolves a method from a dll
|
||||
//
|
||||
// dllmethod: Name of the function exported from the dll
|
||||
// method: Name of the method defined with DEFINE_METHOD
|
||||
// or DEFINE_METHOD_LINKAGE
|
||||
//
|
||||
#define RESOLVE_METHOD_RENAME(dllmethod, method) \
|
||||
m_dll->ResolveExport( #dllmethod , & m_##method##_ptr ) &&
|
||||
|
||||
#define RESOLVE_METHOD_RENAME_FP(dllmethod, method) \
|
||||
m_dll->ResolveExport( #dllmethod , & method##_ptr ) &&
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Example declaration of a dll wrapper class
|
||||
//
|
||||
// 1. Define a class with pure virtual functions with all functions
|
||||
// exported from the dll. This is needed to use the IntelliSence
|
||||
// feature of the Visual Studio Editor.
|
||||
//
|
||||
// class DllExampleInterface
|
||||
// {
|
||||
// public:
|
||||
// virtual void foo (unsigned int type, char* szTest)=0;
|
||||
// virtual void bar (char* szTest, unsigned int type)=0;
|
||||
// };
|
||||
//
|
||||
// 2. Define a class, derived from DllDynamic and the previously defined
|
||||
// interface class. Define the constructor of the class using the
|
||||
// DECLARE_DLL_WRAPPER macro. Use the DEFINE_METHODX/DEFINE_METHOD_LINKAGEX
|
||||
// macros to define the functions from the interface above, where X is number of
|
||||
// parameters the function has. The function parameters
|
||||
// have to be enclosed in parentheses. The parameter names have to be changed to px
|
||||
// where x is the number on which position the parameter appears.
|
||||
// Use the RESOLVE_METHOD/RESOLVE_METHOD_RENAME to do the actually resolve the functions
|
||||
// from the dll when it's loaded. The RESOLVE_METHOD/RESOLVE_METHOD_RENAME have to
|
||||
// be between the BEGIN_METHOD_RESOLVE/END_METHOD_RESOLVE block.
|
||||
//
|
||||
// class DllExample : public DllDynamic, DllExampleInterface
|
||||
// {
|
||||
// DECLARE_DLL_WRAPPER(DllExample, special://xbmcbin/system/Example.dll)
|
||||
// LOAD_SYMBOLS() // add this if you want to load debug symbols for the dll
|
||||
// DEFINE_METHOD2(void, foo, (int p1, char* p2))
|
||||
// DEFINE_METHOD_LINKAGE2(void, __stdcall, bar, (char* p1, int p2))
|
||||
// DEFINE_METHOD_FP(void, foobar, (int type, char* szTest)) // No need to define this function in the
|
||||
// // interface class, as it's a function pointer.
|
||||
// // But its not recognised by IntelliSence
|
||||
// BEGIN_METHOD_RESOLVE()
|
||||
// RESOLVE_METHOD(foo)
|
||||
// RESOLVE_METHOD_RENAME("_bar@8", bar)
|
||||
// RESOLVE_METHOD_FP(foobar)
|
||||
// END_METHOD_RESOLVE()
|
||||
// };
|
||||
//
|
||||
// The above macros will expand to a class that will look like this
|
||||
//
|
||||
// class DllExample : public DllDynamic, DllExampleInterface
|
||||
// {
|
||||
// public:
|
||||
// DllExample() : DllDynamic( "special://xbmcbin/system/Example.dll" ) {}
|
||||
// protected:
|
||||
// virtual bool LoadSymbols() { return true; }
|
||||
// protected:
|
||||
// typedef void (* foo_METHOD) ( int p1, char* p2 );
|
||||
// foo_METHOD m_foo;
|
||||
// public:
|
||||
// virtual void foo( int p1, char* p2 )
|
||||
// {
|
||||
// return m_foo(p1, p2);
|
||||
// }
|
||||
// protected:
|
||||
// typedef void (__stdcall * bar_METHOD) ( char* p1, int p2 );
|
||||
// bar_METHOD m_bar;
|
||||
// public:
|
||||
// virtual void bar( char* p1, int p2 )
|
||||
// {
|
||||
// return m_bar(p1, p2);
|
||||
// }
|
||||
// protected:
|
||||
// typedef void (* foobar_METHOD) (int type, char* szTest);
|
||||
// public:
|
||||
// foobar_METHOD foobar;
|
||||
// protected:
|
||||
// virtual bool ResolveExports()
|
||||
// {
|
||||
// return (
|
||||
// m_dll->ResolveExport( "foo", (void**)& m_foo ) &&
|
||||
// m_dll->ResolveExport( "_bar@8", (void**)& m_bar ) &&
|
||||
// m_dll->ResolveExport( "foobar" , (void**)& foobar ) &&
|
||||
// 1
|
||||
// );
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// Usage of the class
|
||||
//
|
||||
// DllExample dll;
|
||||
// dll.Load();
|
||||
// if (dll.IsLoaded())
|
||||
// {
|
||||
// dll.foo(1, "bar");
|
||||
// dll.Unload();
|
||||
// }
|
||||
//
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
//
|
||||
// Baseclass for a Dynamically loaded dll
|
||||
// use the above macros to create a dll wrapper
|
||||
//
|
||||
class DllDynamic
|
||||
{
|
||||
public:
|
||||
DllDynamic();
|
||||
DllDynamic(const CStdString& strDllName);
|
||||
virtual ~DllDynamic();
|
||||
virtual bool Load();
|
||||
virtual void Unload();
|
||||
virtual bool IsLoaded() { return m_dll!=NULL; }
|
||||
bool CanLoad();
|
||||
bool EnableDelayedUnload(bool bOnOff);
|
||||
bool SetFile(const CStdString& strDllName);
|
||||
|
||||
protected:
|
||||
virtual bool ResolveExports()=0;
|
||||
virtual bool LoadSymbols() { return false; }
|
||||
bool m_DelayUnload;
|
||||
void *m_dll;
|
||||
CStdString m_strDllName;
|
||||
};
|
||||
142
File.cpp
Normal file
142
File.cpp
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* XBMC Media Center
|
||||
* Copyright (c) 2002 Frodo
|
||||
* Portions Copyright (c) by the authors of ffmpeg and xvid
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "linux/PlatformDefs.h"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include "utils/StdString.h"
|
||||
|
||||
#include "File.h"
|
||||
|
||||
using namespace XFILE;
|
||||
using namespace std;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#ifndef __GNUC__
|
||||
#pragma warning (disable:4244)
|
||||
#endif
|
||||
|
||||
//*********************************************************************************************
|
||||
CFile::CFile()
|
||||
{
|
||||
m_pFile = NULL;
|
||||
m_flags = 0;
|
||||
m_iLength = 0;
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
CFile::~CFile()
|
||||
{
|
||||
if (m_pFile)
|
||||
fclose(m_pFile);
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
bool CFile::Open(const CStdString& strFileName, unsigned int flags)
|
||||
{
|
||||
m_flags = flags;
|
||||
|
||||
m_pFile = fopen64(strFileName.c_str(), "r");
|
||||
if(!m_pFile)
|
||||
return false;
|
||||
|
||||
fseeko64(m_pFile, 0, SEEK_END);
|
||||
m_iLength = ftello64(m_pFile);
|
||||
fseeko64(m_pFile, 0, SEEK_SET);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CFile::OpenForWrite(const CStdString& strFileName, bool bOverWrite)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CFile::Exists(const CStdString& strFileName, bool bUseCache /* = true */)
|
||||
{
|
||||
FILE *fp = fopen64(strFileName.c_str(), "r");
|
||||
|
||||
if(!fp)
|
||||
return false;
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int CFile::Read(void *lpBuf, int64_t uiBufSize)
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
|
||||
if(!m_pFile)
|
||||
return 0;
|
||||
|
||||
ret = fread(lpBuf, 1, uiBufSize, m_pFile);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
void CFile::Close()
|
||||
{
|
||||
if(m_pFile)
|
||||
fclose(m_pFile);
|
||||
m_pFile = NULL;
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
int64_t CFile::Seek(int64_t iFilePosition, int iWhence)
|
||||
{
|
||||
if (!m_pFile)
|
||||
return -1;
|
||||
|
||||
return fseeko64(m_pFile, iFilePosition, iWhence);;
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
int64_t CFile::GetLength()
|
||||
{
|
||||
return m_iLength;
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
int64_t CFile::GetPosition()
|
||||
{
|
||||
if (!m_pFile)
|
||||
return -1;
|
||||
|
||||
return ftello64(m_pFile);
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
int CFile::Write(const void* lpBuf, int64_t uiBufSize)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int CFile::IoControl(EIoControl request, void* param)
|
||||
{
|
||||
if(request == IOCTRL_SEEK_POSSIBLE)
|
||||
return 1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
83
File.h
Normal file
83
File.h
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* XBMC Media Center
|
||||
* Copyright (c) 2002 Frodo
|
||||
* Portions Copyright (c) by the authors of ffmpeg and xvid
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
// File.h: interface for the CFile class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(AFX_FILE_H__A7ED6320_C362_49CB_8925_6C6C8CAE7B78__INCLUDED_)
|
||||
#define AFX_FILE_H__A7ED6320_C362_49CB_8925_6C6C8CAE7B78__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#define FFMPEG_FILE_BUFFER_SIZE 32768
|
||||
|
||||
namespace XFILE
|
||||
{
|
||||
|
||||
/* indicate that caller can handle truncated reads, where function returns before entire buffer has been filled */
|
||||
#define READ_TRUNCATED 0x01
|
||||
|
||||
/* indicate that that caller support read in the minimum defined chunk size, this disables internal cache then */
|
||||
#define READ_CHUNKED 0x02
|
||||
|
||||
/* use cache to access this file */
|
||||
#define READ_CACHED 0x04
|
||||
|
||||
/* open without caching. regardless to file type. */
|
||||
#define READ_NO_CACHE 0x08
|
||||
|
||||
/* calcuate bitrate for file while reading */
|
||||
#define READ_BITRATE 0x10
|
||||
|
||||
typedef enum {
|
||||
IOCTRL_NATIVE = 1, /**< SNativeIoControl structure, containing what should be passed to native ioctrl */
|
||||
IOCTRL_SEEK_POSSIBLE = 2, /**< return 0 if known not to work, 1 if it should work */
|
||||
IOCTRL_CACHE_STATUS = 3, /**< SCacheStatus structure */
|
||||
IOCTRL_CACHE_SETRATE = 4, /**< unsigned int with with speed limit for caching in bytes per second */
|
||||
} EIoControl;
|
||||
|
||||
class CFile
|
||||
{
|
||||
public:
|
||||
CFile();
|
||||
~CFile();
|
||||
|
||||
bool Open(const CStdString& strFileName, unsigned int flags = 0);
|
||||
bool OpenForWrite(const CStdString& strFileName, bool bOverWrite);
|
||||
unsigned int Read(void* lpBuf, int64_t uiBufSize);
|
||||
int Write(const void* lpBuf, int64_t uiBufSize);
|
||||
int64_t Seek(int64_t iFilePosition, int iWhence = SEEK_SET);
|
||||
int64_t GetPosition();
|
||||
int64_t GetLength();
|
||||
void Close();
|
||||
static bool Exists(const CStdString& strFileName, bool bUseCache = true);
|
||||
int GetChunkSize() { return 6144 /*FFMPEG_FILE_BUFFER_SIZE*/; };
|
||||
int IoControl(EIoControl request, void* param);
|
||||
private:
|
||||
unsigned int m_flags;
|
||||
FILE *m_pFile;
|
||||
int64_t m_iLength;
|
||||
};
|
||||
|
||||
};
|
||||
#endif // !defined(AFX_FILE_H__A7ED6320_C362_49CB_8925_6C6C8CAE7B78__INCLUDED_)
|
||||
86
IAudioRenderer.h
Normal file
86
IAudioRenderer.h
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* XBMC Media Center
|
||||
* Copyright (c) 2002 d7o3g4q and RUNTiME
|
||||
* Portions Copyright (c) by the authors of ffmpeg and xvid
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
// AsyncAudioRenderer.h: interface for the CAsyncDirectSound class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(AFX_IAUDIORENDERER_H__B590A94D_D15E_43A6_A41D_527BD441B5F5__INCLUDED_)
|
||||
#define AFX_IAUDIORENDERER_H__B590A94D_D15E_43A6_A41D_527BD441B5F5__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "utils/StdString.h"
|
||||
#include "cores/IAudioCallback.h"
|
||||
#include "utils/PCMRemap.h"
|
||||
extern void RegisterAudioCallback(IAudioCallback* pCallback);
|
||||
extern void UnRegisterAudioCallback();
|
||||
|
||||
typedef std::pair<CStdString, CStdString> AudioSink;
|
||||
typedef std::vector<AudioSink> AudioSinkList;
|
||||
|
||||
class IAudioRenderer
|
||||
{
|
||||
public:
|
||||
enum EEncoded {
|
||||
ENCODED_NONE = 0,
|
||||
ENCODED_IEC61937_AC3,
|
||||
ENCODED_IEC61937_EAC3,
|
||||
ENCODED_IEC61937_DTS,
|
||||
ENCODED_IEC61937_MPEG,
|
||||
ENCODED_IEC61937_UNKNOWN,
|
||||
};
|
||||
|
||||
IAudioRenderer() {};
|
||||
virtual ~IAudioRenderer() {};
|
||||
virtual bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, enum PCMChannels *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, bool bIsMusic=false, EEncoded encoded = ENCODED_NONE) = 0;
|
||||
virtual void UnRegisterAudioCallback() = 0;
|
||||
virtual void RegisterAudioCallback(IAudioCallback* pCallback) = 0;
|
||||
virtual float GetDelay() = 0;
|
||||
virtual float GetCacheTime() = 0;
|
||||
virtual float GetCacheTotal() { return 1.0f; }
|
||||
|
||||
virtual unsigned int AddPackets(const void* data, unsigned int len) = 0;
|
||||
virtual bool IsResampling() { return false;};
|
||||
virtual unsigned int GetSpace() = 0;
|
||||
virtual bool Deinitialize() = 0;
|
||||
virtual bool Pause() = 0;
|
||||
virtual bool Stop() = 0;
|
||||
virtual bool Resume() = 0;
|
||||
virtual unsigned int GetChunkLen() = 0;
|
||||
|
||||
virtual long GetCurrentVolume() const = 0;
|
||||
virtual void Mute(bool bMute) = 0;
|
||||
virtual bool SetCurrentVolume(long nVolume) = 0;
|
||||
virtual void SetDynamicRangeCompression(long drc) {};
|
||||
virtual float GetCurrentAttenuation() { return m_remap.GetCurrentAttenuation(); }
|
||||
virtual int SetPlaySpeed(int iSpeed) = 0;
|
||||
virtual void WaitCompletion() = 0;
|
||||
virtual void SwitchChannels(int iAudioStream, bool bAudioOnAllSpeakers) = 0;
|
||||
|
||||
protected:
|
||||
CPCMRemap m_remap;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // !defined(AFX_IAUDIORENDERER_H__B590A94D_D15E_43A6_A41D_527BD441B5F5__INCLUDED_)
|
||||
65
Makefile
Normal file
65
Makefile
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
include Makefile.include
|
||||
|
||||
CFLAGS+=-DSTANDALONE -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS -DTARGET_POSIX -D_LINUX -fPIC -DPIC -D_REENTRANT -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -DHAVE_CMAKE_CONFIG -D__VIDEOCORE4__ -U_FORTIFY_SOURCE -Wall -mfpu=vfp -mfloat-abi=softfp -mno-apcs-stack-check -DHAVE_OMXLIB -DUSE_EXTERNAL_FFMPEG -DHAVE_LIBAVCODEC_AVCODEC_H -DHAVE_LIBAVUTIL_MEM_H -DHAVE_LIBAVUTIL_AVUTIL_H -DHAVE_LIBAVFORMAT_AVFORMAT_H -DHAVE_LIBAVFILTER_AVFILTER_H -DOMX -DOMX_SKIP64BIT -ftree-vectorize -pipe -DUSE_EXTERNAL_OMX -DHAVE_PLATFORM_RASPBERRY_PI -DUSE_EXTERNAL_LIBBCM_HOST -Wno-psabi -I$(SDKSTAGE)/opt/vc/include/
|
||||
|
||||
LDFLAGS+=-L./ -lc -lWFC -lGLESv2 -lEGL -lbcm_host -lopenmaxil -Lffmpeg_compiled/usr/local/lib/
|
||||
INCLUDES+=-I./ -Ilinux -Iffmpeg_compiled/usr/local/include/
|
||||
|
||||
SRC=linux/XMemUtils.cpp \
|
||||
utils/log.cpp \
|
||||
DynamicDll.cpp \
|
||||
utils/PCMRemap.cpp \
|
||||
utils/RegExp.cpp \
|
||||
OMXSubtitleTagSami.cpp \
|
||||
OMXOverlayCodecText.cpp \
|
||||
BitstreamConverter.cpp \
|
||||
linux/RBP.cpp \
|
||||
OMXThread.cpp \
|
||||
OMXReader.cpp \
|
||||
OMXStreamInfo.cpp \
|
||||
OMXAudioCodecOMX.cpp \
|
||||
OMXCore.cpp \
|
||||
OMXVideo.cpp \
|
||||
OMXAudio.cpp \
|
||||
OMXClock.cpp \
|
||||
File.cpp \
|
||||
OMXPlayerVideo.cpp \
|
||||
OMXPlayerAudio.cpp \
|
||||
omxplayer.cpp \
|
||||
|
||||
OBJS+=$(filter %.o,$(SRC:.cpp=.o))
|
||||
|
||||
all: omxplayer.bin
|
||||
|
||||
%.o: %.cpp
|
||||
@rm -f $@
|
||||
$(CXX) $(CFLAGS) $(INCLUDES) -c $< -o $@ -Wno-deprecated-declarations
|
||||
|
||||
list_test:
|
||||
$(CXX) -O3 -o list_test list_test.cpp
|
||||
|
||||
omxplayer.bin: $(OBJS)
|
||||
$(CXX) $(LDFLAGS) -o omxplayer.bin -Wl,--whole-archive $(OBJS) -Wl,--no-whole-archive -rdynamic -lavutil -lavcodec -lavformat -lswscale -lpcre
|
||||
#arm-unknown-linux-gnueabi-strip omxplayer.bin
|
||||
|
||||
clean:
|
||||
for i in $(OBJS); do (if test -e "$$i"; then ( rm $$i ); fi ); done
|
||||
@rm -f omxplayer.old.log omxplayer.log
|
||||
@rm -f omxplayer.bin
|
||||
@rm -rf omxplayer-dist
|
||||
@rm -f omxplayer-dist.tar.gz
|
||||
make -f Makefile.ffmpeg clean
|
||||
|
||||
ffmpeg:
|
||||
@rm -rf ffmpeg
|
||||
make -f Makefile.ffmpeg
|
||||
make -f Makefile.ffmpeg install
|
||||
|
||||
dist: omxplayer.bin
|
||||
mkdir -p omxplayer-dist/usr/lib/omxplayer
|
||||
mkdir -p omxplayer-dist/usr/usr/bin
|
||||
mkdir -p omxplayer-dist/usr/share/doc
|
||||
cp omxplayer omxplayer.bin omxplayer-dist/usr/usr/bin
|
||||
cp README COPYING omxplayer-dist/usr/share/doc/
|
||||
cp -a ffmpeg_compiled/usr/local/lib/*.so* omxplayer-dist/usr/lib/omxplayer/
|
||||
tar -czf omxplayer-dist.tar.gz omxplayer-dist
|
||||
70
Makefile.ffmpeg
Normal file
70
Makefile.ffmpeg
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
include Makefile.include
|
||||
|
||||
CFLAGS=-D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS -DTARGET_POSIX -D_LINUX -fPIC -DPIC -D_REENTRANT -D_HAVE_SBRK -D_LARGEFILE64_SOURCE -DHAVE_CMAKE_CONFIG -DHAVE_VMCS_CONFIG -D_REENTRANT -DUSE_VCHIQ_ARM -DVCHI_BULK_ALIGN=1 -DVCHI_BULK_GRANULARITY=1 -DEGL_SERVER_DISPMANX -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D__VIDEOCORE4__ -DGRAPHICS_X_VG=1 -U_FORTIFY_SOURCE -Wall -DHAVE_OMXLIB -DUSE_EXTERNAL_FFMPEG -DHAVE_LIBAVCODEC_AVCODEC_H -DHAVE_LIBAVUTIL_MEM_H -DHAVE_LIBAVUTIL_AVUTIL_H -DHAVE_LIBAVFORMAT_AVFORMAT_H -DHAVE_LIBAVFILTER_AVFILTER_H -DOMX -DOMX_SKIP64BIT
|
||||
|
||||
WORK=$(PWD)
|
||||
|
||||
all: checkout configure compile
|
||||
|
||||
copy:
|
||||
find ffmpeg -name '*.so*' -exec cp {} . \;
|
||||
$(HOST)-strip *.so*
|
||||
|
||||
compile:
|
||||
cd ffmpeg; \
|
||||
make -j9
|
||||
|
||||
configure:
|
||||
cd ffmpeg; \
|
||||
CFLAGS="$(CFLAGS) ${INCLUDES}" \
|
||||
LDFLAGS="" \
|
||||
./configure \
|
||||
--extra-cflags="-mfpu=vfp -mfloat-abi=softfp -mno-apcs-stack-check -mstructure-size-boundary=32 -mno-sched-prolog" \
|
||||
--enable-cross-compile \
|
||||
--enable-shared \
|
||||
--disable-static \
|
||||
--arch=arm \
|
||||
--cpu=arm1176jzf-s \
|
||||
--target-os=linux \
|
||||
--disable-muxers \
|
||||
--enable-muxer=spdif \
|
||||
--enable-muxer=adts \
|
||||
--disable-encoders \
|
||||
--enable-encoder=ac3 \
|
||||
--enable-encoder=aac \
|
||||
--disable-decoder=mpeg_xvmc \
|
||||
--disable-devices \
|
||||
--disable-ffprobe \
|
||||
--disable-ffplay \
|
||||
--disable-ffserver \
|
||||
--disable-ffmpeg \
|
||||
--enable-shared \
|
||||
--disable-doc \
|
||||
--enable-postproc \
|
||||
--enable-gpl \
|
||||
--enable-protocol=http \
|
||||
--enable-pthreads \
|
||||
--disable-runtime-cpudetect \
|
||||
--enable-pic \
|
||||
--disable-armv5te \
|
||||
--disable-neon \
|
||||
--enable-armv6t2 \
|
||||
--enable-armv6 \
|
||||
--enable-armvfp \
|
||||
--enable-hardcoded-tables \
|
||||
--disable-runtime-cpudetect \
|
||||
--disable-debug \
|
||||
--cross-prefix=$(HOST)-
|
||||
|
||||
clean:
|
||||
@rm -rf ffmpeg
|
||||
|
||||
checkout:
|
||||
git clone git://git.videolan.org/ffmpeg.git ffmpeg; \
|
||||
cd ffmpeg; git checkout master; git checkout 67f5650a78de2567c58dbd7545434cc6d3ef9b7e
|
||||
#cd ffmpeg; git checkout master; git checkout ec09230c9a11fbac602380614b35a51ad3a8dc3a
|
||||
|
||||
install:
|
||||
cd ffmpeg; make -j9 DESTDIR="$(WORK)/ffmpeg_compiled" install
|
||||
$(HOST)-strip ffmpeg_compiled/usr/local/lib/*.so
|
||||
|
||||
37
Makefile.include
Normal file
37
Makefile.include
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
USE_BUILDROOT=1
|
||||
|
||||
ifeq ($(USE_BUILDROOT), 1)
|
||||
BUILDROOT :=/opt/xbmc-bcm/buildroot
|
||||
SDKSTAGE :=$(BUILDROOT)/output/staging
|
||||
TARGETFS :=$(BUILDROOT)/output/target
|
||||
TOOLCHAIN :=$(BUILDROOT)/output/host/usr/
|
||||
HOST :=arm-unknown-linux-gnueabi
|
||||
SYSROOT :=$(BUILDROOT)/output/host/usr/arm-unknown-linux-gnueabi/sysroot
|
||||
else
|
||||
BUILDROOT :=/opt/bcm-rootfs
|
||||
SDKSTAGE :=/opt/bcm-rootfs
|
||||
TARGETFS :=/opt/bcm-rootfs
|
||||
TOOLCHAIN :=/usr/local/bcm-gcc
|
||||
HOST :=bcm2708
|
||||
SYSROOT :=$(TOOLCHAIN)/arm-bcm2708-linux-gnueabi/sys-root
|
||||
endif
|
||||
|
||||
JOBS=7
|
||||
|
||||
CFLAGS := -isystem$(PREFIX)/include
|
||||
CXXFLAGS := $(CFLAGS)
|
||||
CPPFLAGS := $(CFLAGS)
|
||||
LDFLAGS := -L$(BUILDROOT)/lib
|
||||
LD := $(TOOLCHAIN)/bin/$(HOST)-ld --sysroot=$(SYSROOT)
|
||||
CC := $(TOOLCHAIN)/bin/$(HOST)-gcc --sysroot=$(SYSROOT)
|
||||
CXX := $(TOOLCHAIN)/bin/$(HOST)-g++ --sysroot=$(SYSROOT)
|
||||
OBJDUMP := $(TOOLCHAIN)/bin/$(HOST)-objdump
|
||||
RANLIB := $(TOOLCHAIN)/bin/$(HOST)-ranlib
|
||||
STRIP := $(TOOLCHAIN)/bin/$(HOST)-strip
|
||||
AR := $(TOOLCHAIN)/bin/$(HOST)-ar
|
||||
CXXCP := $(CXX) -E
|
||||
PATH := $(PREFIX)/bin:$(BUILDROOT)/output/host/usr/bin:$(PATH)
|
||||
|
||||
CFLAGS += -pipe -mfloat-abi=softfp -mcpu=arm1176jzf-s -fomit-frame-pointer -mabi=aapcs-linux -mtune=arm1176jzf-s -mfpu=vfp -Wno-psabi -mno-apcs-stack-check -O3 -mstructure-size-boundary=32 -mno-sched-prolog
|
||||
LDFLAGS += -L$(SDKSTAGE)/lib -L$(SDKSTAGE)/usr/lib -L$(SDKSTAGE)/opt/vc/lib/
|
||||
INCLUDES += -isystem$(SDKSTAGE)/staging/usr/include -isystem$(SDKSTAGE)/staging/opt/vc/include -isystem$(SYSROOT)/usr/include
|
||||
1466
OMXAudio.cpp
Normal file
1466
OMXAudio.cpp
Normal file
File diff suppressed because it is too large
Load diff
143
OMXAudio.h
Normal file
143
OMXAudio.h
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* XBMC Media Center
|
||||
* Copyright (c) 2002 d7o3g4q and RUNTiME
|
||||
* Portions Copyright (c) by the authors of ffmpeg and xvid
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __OPENMAXAUDIORENDER_H__
|
||||
#define __OPENMAXAUDIORENDER_H__
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
//#define STANDALONE
|
||||
|
||||
#ifdef STANDALONE
|
||||
#include "IAudioRenderer.h"
|
||||
#else
|
||||
#include "../AudioRenderers/IAudioRenderer.h"
|
||||
#endif
|
||||
#include "cores/IAudioCallback.h"
|
||||
#include "linux/PlatformDefs.h"
|
||||
#include "DllAvCodec.h"
|
||||
#include "DllAvUtil.h"
|
||||
#include "OMXCore.h"
|
||||
#include "OMXClock.h"
|
||||
#include "OMXStreamInfo.h"
|
||||
#include "BitstreamConverter.h"
|
||||
|
||||
#define AUDIO_BUFFER_SECONDS 2
|
||||
#define VIS_PACKET_SIZE 3840
|
||||
|
||||
class COMXAudio : public IAudioRenderer
|
||||
{
|
||||
public:
|
||||
void UnRegisterAudioCallback();
|
||||
void RegisterAudioCallback(IAudioCallback* pCallback);
|
||||
unsigned int GetChunkLen();
|
||||
float GetDelay();
|
||||
float GetCacheTime();
|
||||
float GetCacheTotal();
|
||||
COMXAudio();
|
||||
bool Initialize(IAudioCallback* pCallback, const CStdString& device, enum PCMChannels *channelMap,
|
||||
COMXStreamInfo &hints, OMXClock *clock, EEncoded bPassthrough, bool bUseHWDecode);
|
||||
bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, enum PCMChannels *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, bool bIsMusic=false, EEncoded bPassthrough = IAudioRenderer::ENCODED_NONE);
|
||||
~COMXAudio();
|
||||
|
||||
unsigned int AddPackets(const void* data, unsigned int len);
|
||||
unsigned int AddPackets(const void* data, unsigned int len, double dts, double pts);
|
||||
unsigned int GetSpace();
|
||||
bool Deinitialize();
|
||||
bool Pause();
|
||||
bool Stop();
|
||||
bool Resume();
|
||||
|
||||
long GetCurrentVolume() const;
|
||||
void Mute(bool bMute);
|
||||
bool SetCurrentVolume(long nVolume);
|
||||
void SetDynamicRangeCompression(long drc) { m_drc = drc; }
|
||||
int SetPlaySpeed(int iSpeed);
|
||||
void WaitCompletion();
|
||||
void SwitchChannels(int iAudioStream, bool bAudioOnAllSpeakers);
|
||||
|
||||
void Flush();
|
||||
void DoAudioWork();
|
||||
static void EnumerateAudioSinks(AudioSinkList& vAudioSinks, bool passthrough);
|
||||
|
||||
void Process();
|
||||
|
||||
bool SetClock(OMXClock *clock);
|
||||
void SetCodingType(CodecID codec);
|
||||
bool CanHWDecode(CodecID codec);
|
||||
static bool HWDecode(CodecID codec);
|
||||
|
||||
void PrintChannels(OMX_AUDIO_CHANNELTYPE eChannelMapping[]);
|
||||
void PrintPCM(OMX_AUDIO_PARAM_PCMMODETYPE *pcm);
|
||||
void PrintDDP(OMX_AUDIO_PARAM_DDPTYPE *ddparm);
|
||||
void PrintDTS(OMX_AUDIO_PARAM_DTSTYPE *dtsparam);
|
||||
unsigned int SyncDTS(BYTE* pData, unsigned int iSize);
|
||||
unsigned int SyncAC3(BYTE* pData, unsigned int iSize);
|
||||
|
||||
private:
|
||||
IAudioCallback* m_pCallback;
|
||||
bool m_Initialized;
|
||||
bool m_Pause;
|
||||
bool m_CanPause;
|
||||
long m_CurrentVolume;
|
||||
long m_drc;
|
||||
bool m_Passthrough;
|
||||
bool m_HWDecode;
|
||||
unsigned int m_BytesPerSec;
|
||||
unsigned int m_BufferLen;
|
||||
unsigned int m_ChunkLen;
|
||||
unsigned int m_InputChannels;
|
||||
unsigned int m_OutputChannels;
|
||||
unsigned int m_BitsPerSample;
|
||||
COMXCoreComponent *m_omx_clock;
|
||||
OMXClock *m_av_clock;
|
||||
bool m_external_clock;
|
||||
bool m_setStartTime;
|
||||
int m_SampleSize;
|
||||
bool m_first_frame;
|
||||
bool m_LostSync;
|
||||
int m_SampleRate;
|
||||
OMX_AUDIO_CODINGTYPE m_eEncoding;
|
||||
uint8_t *m_extradata;
|
||||
int m_extrasize;
|
||||
// stuff for visualisation
|
||||
unsigned int m_visBufferLength;
|
||||
double m_last_pts;
|
||||
short m_visBuffer[VIS_PACKET_SIZE+2];
|
||||
OMX_AUDIO_PARAM_PCMMODETYPE m_pcm_output;
|
||||
OMX_AUDIO_PARAM_PCMMODETYPE m_pcm_input;
|
||||
OMX_AUDIO_PARAM_DTSTYPE m_dtsParam;
|
||||
WAVEFORMATEXTENSIBLE m_wave_header;
|
||||
|
||||
protected:
|
||||
COMXCoreComponent m_omx_render;
|
||||
COMXCoreComponent m_omx_mixer;
|
||||
COMXCoreComponent m_omx_decoder;
|
||||
COMXCoreTunel m_omx_tunnel_clock;
|
||||
COMXCoreTunel m_omx_tunnel_mixer;
|
||||
COMXCoreTunel m_omx_tunnel_decoder;
|
||||
DllAvUtil m_dllAvUtil;
|
||||
};
|
||||
#endif
|
||||
|
||||
351
OMXAudioCodecOMX.cpp
Normal file
351
OMXAudioCodecOMX.cpp
Normal file
|
|
@ -0,0 +1,351 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "OMXAudioCodecOMX.h"
|
||||
#ifdef _LINUX
|
||||
#include "XMemUtils.h"
|
||||
#endif
|
||||
#include "utils/log.h"
|
||||
|
||||
#define MAX_AUDIO_FRAME_SIZE (AVCODEC_MAX_AUDIO_FRAME_SIZE*1.5)
|
||||
|
||||
COMXAudioCodecOMX::COMXAudioCodecOMX()
|
||||
{
|
||||
m_iBufferSize1 = 0;
|
||||
m_pBuffer1 = (BYTE*)_aligned_malloc(MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE, 16);
|
||||
memset(m_pBuffer1, 0, MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
|
||||
m_iBufferSize2 = 0;
|
||||
m_pBuffer2 = (BYTE*)_aligned_malloc(MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE, 16);
|
||||
memset(m_pBuffer2, 0, MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
|
||||
m_iBuffered = 0;
|
||||
m_pCodecContext = NULL;
|
||||
m_pConvert = NULL;
|
||||
m_bOpenedCodec = false;
|
||||
|
||||
m_channelMap[0] = PCM_INVALID;
|
||||
m_channels = 0;
|
||||
m_layout = 0;
|
||||
}
|
||||
|
||||
COMXAudioCodecOMX::~COMXAudioCodecOMX()
|
||||
{
|
||||
_aligned_free(m_pBuffer1);
|
||||
_aligned_free(m_pBuffer2);
|
||||
|
||||
Dispose();
|
||||
}
|
||||
|
||||
bool COMXAudioCodecOMX::Open(COMXStreamInfo &hints)
|
||||
{
|
||||
AVCodec* pCodec;
|
||||
m_bOpenedCodec = false;
|
||||
|
||||
if (!m_dllAvCore.Load() || !m_dllAvUtil.Load() || !m_dllAvCodec.Load())
|
||||
return false;
|
||||
|
||||
m_dllAvCodec.avcodec_register_all();
|
||||
m_pCodecContext = m_dllAvCodec.avcodec_alloc_context();
|
||||
m_dllAvCodec.avcodec_get_context_defaults(m_pCodecContext);
|
||||
|
||||
pCodec = m_dllAvCodec.avcodec_find_decoder(hints.codec);
|
||||
if (!pCodec)
|
||||
{
|
||||
CLog::Log(LOGDEBUG,"COMXAudioCodecOMX::Open() Unable to find codec %d", hints.codec);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pCodecContext->debug_mv = 0;
|
||||
m_pCodecContext->debug = 0;
|
||||
m_pCodecContext->workaround_bugs = 1;
|
||||
|
||||
if (pCodec->capabilities & CODEC_CAP_TRUNCATED)
|
||||
m_pCodecContext->flags |= CODEC_FLAG_TRUNCATED;
|
||||
|
||||
m_channels = 0;
|
||||
m_pCodecContext->channels = hints.channels;
|
||||
m_pCodecContext->sample_rate = hints.samplerate;
|
||||
m_pCodecContext->block_align = hints.blockalign;
|
||||
m_pCodecContext->bit_rate = hints.bitrate;
|
||||
m_pCodecContext->bits_per_coded_sample = hints.bitspersample;
|
||||
|
||||
if(m_pCodecContext->bits_per_coded_sample == 0)
|
||||
m_pCodecContext->bits_per_coded_sample = 16;
|
||||
|
||||
if( hints.extradata && hints.extrasize > 0 )
|
||||
{
|
||||
m_pCodecContext->extradata_size = hints.extrasize;
|
||||
m_pCodecContext->extradata = (uint8_t*)m_dllAvUtil.av_mallocz(hints.extrasize + FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
memcpy(m_pCodecContext->extradata, hints.extradata, hints.extrasize);
|
||||
}
|
||||
|
||||
if (m_dllAvCodec.avcodec_open(m_pCodecContext, pCodec) < 0)
|
||||
{
|
||||
CLog::Log(LOGDEBUG,"COMXAudioCodecOMX::Open() Unable to open codec");
|
||||
Dispose();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_bOpenedCodec = true;
|
||||
m_iSampleFormat = AV_SAMPLE_FMT_NONE;
|
||||
return true;
|
||||
}
|
||||
|
||||
void COMXAudioCodecOMX::Dispose()
|
||||
{
|
||||
if (m_pConvert)
|
||||
{
|
||||
m_dllAvCodec.av_audio_convert_free(m_pConvert);
|
||||
m_pConvert = NULL;
|
||||
|
||||
}
|
||||
|
||||
if (m_pCodecContext)
|
||||
{
|
||||
if (m_bOpenedCodec) m_dllAvCodec.avcodec_close(m_pCodecContext);
|
||||
m_bOpenedCodec = false;
|
||||
m_dllAvUtil.av_free(m_pCodecContext);
|
||||
m_pCodecContext = NULL;
|
||||
}
|
||||
|
||||
m_dllAvCodec.Unload();
|
||||
m_dllAvUtil.Unload();
|
||||
|
||||
m_iBufferSize1 = 0;
|
||||
m_iBufferSize2 = 0;
|
||||
m_iBuffered = 0;
|
||||
}
|
||||
|
||||
int COMXAudioCodecOMX::Decode(BYTE* pData, int iSize)
|
||||
{
|
||||
int iBytesUsed;
|
||||
if (!m_pCodecContext) return -1;
|
||||
if (iSize < 1) return iSize;
|
||||
|
||||
m_iBufferSize1 = AVCODEC_MAX_AUDIO_FRAME_SIZE;
|
||||
m_iBufferSize2 = 0;
|
||||
|
||||
AVPacket avpkt;
|
||||
m_dllAvCodec.av_init_packet(&avpkt);
|
||||
avpkt.data = pData;
|
||||
avpkt.size = iSize;
|
||||
iBytesUsed = m_dllAvCodec.avcodec_decode_audio3( m_pCodecContext
|
||||
, (int16_t*)m_pBuffer1
|
||||
, &m_iBufferSize1
|
||||
, &avpkt);
|
||||
|
||||
/* some codecs will attempt to consume more data than what we gave */
|
||||
if (iBytesUsed > iSize)
|
||||
{
|
||||
CLog::Log(LOGWARNING, "COMXAudioCodecOMX::Decode - decoder attempted to consume more data than given");
|
||||
iBytesUsed = iSize;
|
||||
}
|
||||
|
||||
if(m_iBufferSize1 == 0 && iBytesUsed >= 0)
|
||||
m_iBuffered += iBytesUsed;
|
||||
else
|
||||
m_iBuffered = 0;
|
||||
|
||||
if(m_pCodecContext->sample_fmt != AV_SAMPLE_FMT_S16 && m_iBufferSize1 > 0)
|
||||
{
|
||||
if(m_pConvert && m_pCodecContext->sample_fmt != m_iSampleFormat)
|
||||
{
|
||||
m_dllAvCodec.av_audio_convert_free(m_pConvert);
|
||||
m_pConvert = NULL;
|
||||
}
|
||||
|
||||
if(!m_pConvert)
|
||||
{
|
||||
m_iSampleFormat = m_pCodecContext->sample_fmt;
|
||||
m_pConvert = m_dllAvCodec.av_audio_convert_alloc(AV_SAMPLE_FMT_S16, 1, m_pCodecContext->sample_fmt, 1, NULL, 0);
|
||||
}
|
||||
|
||||
if(!m_pConvert)
|
||||
{
|
||||
CLog::Log(LOGERROR, "COMXAudioCodecOMX::Decode - Unable to convert %d to AV_SAMPLE_FMT_S16", m_pCodecContext->sample_fmt);
|
||||
m_iBufferSize1 = 0;
|
||||
m_iBufferSize2 = 0;
|
||||
return iBytesUsed;
|
||||
}
|
||||
|
||||
const void *ibuf[6] = { m_pBuffer1 };
|
||||
void *obuf[6] = { m_pBuffer2 };
|
||||
int istr[6] = { m_dllAvCore.av_get_bits_per_sample_fmt(m_pCodecContext->sample_fmt)/8 };
|
||||
int ostr[6] = { 2 };
|
||||
int len = m_iBufferSize1 / istr[0];
|
||||
if(m_dllAvCodec.av_audio_convert(m_pConvert, obuf, ostr, ibuf, istr, len) < 0)
|
||||
{
|
||||
CLog::Log(LOGERROR, "COMXAudioCodecOMX::Decode - Unable to convert %d to AV_SAMPLE_FMT_S16", (int)m_pCodecContext->sample_fmt);
|
||||
m_iBufferSize1 = 0;
|
||||
m_iBufferSize2 = 0;
|
||||
return iBytesUsed;
|
||||
}
|
||||
|
||||
m_iBufferSize1 = 0;
|
||||
m_iBufferSize2 = len * ostr[0];
|
||||
}
|
||||
|
||||
return iBytesUsed;
|
||||
}
|
||||
|
||||
int COMXAudioCodecOMX::GetData(BYTE** dst)
|
||||
{
|
||||
// TODO: Use a third buffer and decide which is our source data
|
||||
if(m_pCodecContext->channels == 6 && m_iBufferSize1)
|
||||
{
|
||||
int16_t *pDst = (int16_t *)m_pBuffer2;
|
||||
int16_t *pSrc = (int16_t *)m_pBuffer1;
|
||||
|
||||
//printf("\ncopy_chunk_len %d, omx_chunk_len %d\n", copy_chunk_len, omx_chunk_len);
|
||||
memset(m_pBuffer2, 0, MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
|
||||
m_iBufferSize2 = 0;
|
||||
int size = m_iBufferSize1 / 2;
|
||||
int gap = 8 - m_pCodecContext->channels;
|
||||
int samples = 0;
|
||||
|
||||
for(int i = 0; i < size; pDst++, pSrc++, i++, samples++)
|
||||
{
|
||||
if( (i%m_pCodecContext->channels) == 0)
|
||||
{
|
||||
pDst += gap;
|
||||
samples += gap;
|
||||
}
|
||||
|
||||
*pDst = *pSrc;
|
||||
}
|
||||
|
||||
m_iBufferSize2 = samples * 2;
|
||||
|
||||
*dst = m_pBuffer2;
|
||||
return m_iBufferSize2;
|
||||
}
|
||||
|
||||
if(m_iBufferSize1)
|
||||
{
|
||||
*dst = m_pBuffer1;
|
||||
return m_iBufferSize1;
|
||||
}
|
||||
if(m_iBufferSize2)
|
||||
{
|
||||
*dst = m_pBuffer2;
|
||||
return m_iBufferSize2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void COMXAudioCodecOMX::Reset()
|
||||
{
|
||||
if (m_pCodecContext) m_dllAvCodec.avcodec_flush_buffers(m_pCodecContext);
|
||||
m_iBufferSize1 = 0;
|
||||
m_iBufferSize2 = 0;
|
||||
m_iBuffered = 0;
|
||||
}
|
||||
|
||||
int COMXAudioCodecOMX::GetChannels()
|
||||
{
|
||||
return (m_pCodecContext->channels == 6) ? 8 : m_pCodecContext->channels;
|
||||
}
|
||||
|
||||
int COMXAudioCodecOMX::GetSampleRate()
|
||||
{
|
||||
if (m_pCodecContext) return m_pCodecContext->sample_rate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int COMXAudioCodecOMX::GetBitsPerSample()
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
|
||||
int COMXAudioCodecOMX::GetBitRate()
|
||||
{
|
||||
if (m_pCodecContext) return m_pCodecContext->bit_rate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned count_bits(int64_t value)
|
||||
{
|
||||
unsigned bits = 0;
|
||||
for(;value;++bits)
|
||||
value &= value - 1;
|
||||
return bits;
|
||||
}
|
||||
|
||||
void COMXAudioCodecOMX::BuildChannelMap()
|
||||
{
|
||||
if (m_channels == m_pCodecContext->channels && m_layout == m_pCodecContext->channel_layout)
|
||||
return; //nothing to do here
|
||||
|
||||
m_channels = m_pCodecContext->channels;
|
||||
m_layout = m_pCodecContext->channel_layout;
|
||||
|
||||
int64_t layout;
|
||||
|
||||
int bits = count_bits(m_pCodecContext->channel_layout);
|
||||
if (bits == m_pCodecContext->channels)
|
||||
layout = m_pCodecContext->channel_layout;
|
||||
else
|
||||
{
|
||||
CLog::Log(LOGINFO, "COMXAudioCodecOMX::GetChannelMap - FFmpeg reported %d channels, but the layout contains %d ignoring", m_pCodecContext->channels, bits);
|
||||
layout = m_dllAvCodec.avcodec_guess_channel_layout(m_pCodecContext->channels, m_pCodecContext->codec_id, NULL);
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
if (layout & AV_CH_FRONT_LEFT ) m_channelMap[index++] = PCM_FRONT_LEFT ;
|
||||
if (layout & AV_CH_FRONT_RIGHT ) m_channelMap[index++] = PCM_FRONT_RIGHT ;
|
||||
if (layout & AV_CH_FRONT_CENTER ) m_channelMap[index++] = PCM_FRONT_CENTER ;
|
||||
if (layout & AV_CH_LOW_FREQUENCY ) m_channelMap[index++] = PCM_LOW_FREQUENCY ;
|
||||
if (layout & AV_CH_BACK_LEFT ) m_channelMap[index++] = PCM_BACK_LEFT ;
|
||||
if (layout & AV_CH_BACK_RIGHT ) m_channelMap[index++] = PCM_BACK_RIGHT ;
|
||||
if (layout & AV_CH_FRONT_LEFT_OF_CENTER ) m_channelMap[index++] = PCM_FRONT_LEFT_OF_CENTER ;
|
||||
if (layout & AV_CH_FRONT_RIGHT_OF_CENTER) m_channelMap[index++] = PCM_FRONT_RIGHT_OF_CENTER;
|
||||
if (layout & AV_CH_BACK_CENTER ) m_channelMap[index++] = PCM_BACK_CENTER ;
|
||||
if (layout & AV_CH_SIDE_LEFT ) m_channelMap[index++] = PCM_SIDE_LEFT ;
|
||||
if (layout & AV_CH_SIDE_RIGHT ) m_channelMap[index++] = PCM_SIDE_RIGHT ;
|
||||
if (layout & AV_CH_TOP_CENTER ) m_channelMap[index++] = PCM_TOP_CENTER ;
|
||||
if (layout & AV_CH_TOP_FRONT_LEFT ) m_channelMap[index++] = PCM_TOP_FRONT_LEFT ;
|
||||
if (layout & AV_CH_TOP_FRONT_CENTER ) m_channelMap[index++] = PCM_TOP_FRONT_CENTER ;
|
||||
if (layout & AV_CH_TOP_FRONT_RIGHT ) m_channelMap[index++] = PCM_TOP_FRONT_RIGHT ;
|
||||
if (layout & AV_CH_TOP_BACK_LEFT ) m_channelMap[index++] = PCM_TOP_BACK_LEFT ;
|
||||
if (layout & AV_CH_TOP_BACK_CENTER ) m_channelMap[index++] = PCM_TOP_BACK_CENTER ;
|
||||
if (layout & AV_CH_TOP_BACK_RIGHT ) m_channelMap[index++] = PCM_TOP_BACK_RIGHT ;
|
||||
|
||||
//terminate the channel map
|
||||
m_channelMap[index] = PCM_INVALID;
|
||||
if(m_pCodecContext->channels == 6)
|
||||
{
|
||||
m_channelMap[6] = PCM_INVALID;
|
||||
m_channelMap[7] = PCM_INVALID;
|
||||
m_channelMap[8] = PCM_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
enum PCMChannels* COMXAudioCodecOMX::GetChannelMap()
|
||||
{
|
||||
BuildChannelMap();
|
||||
|
||||
if (m_channelMap[0] == PCM_INVALID)
|
||||
return NULL;
|
||||
|
||||
return m_channelMap;
|
||||
}
|
||||
74
OMXAudioCodecOMX.h
Normal file
74
OMXAudioCodecOMX.h
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "DllAvCodec.h"
|
||||
#include "DllAvCore.h"
|
||||
#include "DllAvFormat.h"
|
||||
#include "DllAvUtil.h"
|
||||
|
||||
#include "OMXStreamInfo.h"
|
||||
#include "utils/PCMRemap.h"
|
||||
#include "linux/PlatformDefs.h"
|
||||
|
||||
class COMXAudioCodecOMX
|
||||
{
|
||||
public:
|
||||
COMXAudioCodecOMX();
|
||||
~COMXAudioCodecOMX();
|
||||
bool Open(COMXStreamInfo &hints);
|
||||
void Dispose();
|
||||
int Decode(BYTE* pData, int iSize);
|
||||
int GetData(BYTE** dst);
|
||||
void Reset();
|
||||
int GetChannels();
|
||||
enum PCMChannels *GetChannelMap();
|
||||
int GetSampleRate();
|
||||
int GetBitsPerSample();
|
||||
const char* GetName() { return "FFmpeg"; }
|
||||
int GetBufferSize() { return m_iBuffered; }
|
||||
int GetBitRate();
|
||||
|
||||
protected:
|
||||
AVCodecContext* m_pCodecContext;
|
||||
AVAudioConvert* m_pConvert;;
|
||||
enum AVSampleFormat m_iSampleFormat;
|
||||
enum PCMChannels m_channelMap[PCM_MAX_CH + 1];
|
||||
|
||||
BYTE *m_pBuffer1;
|
||||
int m_iBufferSize1;
|
||||
|
||||
BYTE *m_pBuffer2;
|
||||
int m_iBufferSize2;
|
||||
|
||||
bool m_bOpenedCodec;
|
||||
int m_iBuffered;
|
||||
|
||||
int m_channels;
|
||||
uint64_t m_layout;
|
||||
|
||||
DllAvCodec m_dllAvCodec;
|
||||
DllAvCore m_dllAvCore;
|
||||
DllAvUtil m_dllAvUtil;
|
||||
|
||||
void BuildChannelMap();
|
||||
};
|
||||
688
OMXClock.cpp
Normal file
688
OMXClock.cpp
Normal file
|
|
@ -0,0 +1,688 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#if (defined HAVE_CONFIG_H) && (!defined WIN32)
|
||||
#include "config.h"
|
||||
#elif defined(_WIN32)
|
||||
#include "system.h"
|
||||
#endif
|
||||
|
||||
#include "OMXClock.h"
|
||||
|
||||
int64_t OMXClock::m_systemOffset;
|
||||
int64_t OMXClock::m_systemFrequency;
|
||||
bool OMXClock::m_ismasterclock;
|
||||
|
||||
OMXClock::OMXClock()
|
||||
{
|
||||
m_dllAvFormat.Load();
|
||||
|
||||
m_video_clock = DVD_NOPTS_VALUE;
|
||||
m_audio_clock = DVD_NOPTS_VALUE;
|
||||
m_has_video = false;
|
||||
m_has_audio = false;
|
||||
m_play_speed = 1;
|
||||
m_pause = false;
|
||||
m_iCurrentPts = DVD_NOPTS_VALUE;
|
||||
|
||||
m_systemFrequency = CurrentHostFrequency();
|
||||
m_systemUsed = m_systemFrequency;
|
||||
m_pauseClock = 0;
|
||||
m_bReset = true;
|
||||
m_iDisc = 0;
|
||||
m_maxspeedadjust = 0.0;
|
||||
m_speedadjust = false;
|
||||
m_ismasterclock = true;
|
||||
m_ClockOffset = 0;
|
||||
m_fps = 25.0f;
|
||||
|
||||
pthread_mutex_init(&m_lock, NULL);
|
||||
|
||||
CheckSystemClock();
|
||||
|
||||
OMXReset();
|
||||
}
|
||||
|
||||
OMXClock::~OMXClock()
|
||||
{
|
||||
Deinitialize();
|
||||
|
||||
m_dllAvFormat.Unload();
|
||||
pthread_mutex_destroy(&m_lock);
|
||||
}
|
||||
|
||||
void OMXClock::Lock()
|
||||
{
|
||||
pthread_mutex_lock(&m_lock);
|
||||
}
|
||||
|
||||
void OMXClock::UnLock()
|
||||
{
|
||||
pthread_mutex_unlock(&m_lock);
|
||||
}
|
||||
|
||||
double OMXClock::SystemToAbsolute(int64_t system)
|
||||
{
|
||||
return DVD_TIME_BASE * (double)(system - m_systemOffset) / m_systemFrequency;
|
||||
}
|
||||
|
||||
double OMXClock::SystemToPlaying(int64_t system)
|
||||
{
|
||||
int64_t current;
|
||||
|
||||
if (m_bReset)
|
||||
{
|
||||
m_startClock = system;
|
||||
m_systemUsed = m_systemFrequency;
|
||||
m_pauseClock = 0;
|
||||
m_iDisc = 0;
|
||||
m_bReset = false;
|
||||
}
|
||||
|
||||
if (m_pauseClock)
|
||||
current = m_pauseClock;
|
||||
else
|
||||
current = system;
|
||||
|
||||
return DVD_TIME_BASE * (double)(current - m_startClock) / m_systemUsed + m_iDisc;
|
||||
}
|
||||
|
||||
int64_t OMXClock::GetFrequency()
|
||||
{
|
||||
return m_systemFrequency;
|
||||
}
|
||||
|
||||
int64_t OMXClock::Wait(int64_t Target)
|
||||
{
|
||||
int64_t Now;
|
||||
int SleepTime;
|
||||
int64_t ClockOffset = m_ClockOffset;
|
||||
|
||||
Now = CurrentHostCounter();
|
||||
//sleep until the timestamp has passed
|
||||
SleepTime = (int)((Target - (Now + ClockOffset)) * 1000 / m_systemFrequency);
|
||||
if (SleepTime > 0)
|
||||
OMXSleep(SleepTime);
|
||||
|
||||
Now = CurrentHostCounter();
|
||||
return Now;
|
||||
}
|
||||
|
||||
double OMXClock::WaitAbsoluteClock(double target)
|
||||
{
|
||||
Lock();
|
||||
int64_t systemtarget, freq, offset;
|
||||
freq = m_systemFrequency;
|
||||
offset = m_systemOffset;
|
||||
UnLock();
|
||||
|
||||
systemtarget = (int64_t)(target / DVD_TIME_BASE * (double)freq);
|
||||
systemtarget += offset;
|
||||
systemtarget = Wait(systemtarget);
|
||||
systemtarget -= offset;
|
||||
return (double)systemtarget / freq * DVD_TIME_BASE;
|
||||
}
|
||||
|
||||
// Returns the current absolute clock in units of DVD_TIME_BASE (usually microseconds).
|
||||
double OMXClock::GetAbsoluteClock(bool interpolated /*= true*/)
|
||||
{
|
||||
Lock();
|
||||
CheckSystemClock();
|
||||
double current = GetTime();
|
||||
UnLock();
|
||||
return SystemToAbsolute(current);
|
||||
}
|
||||
|
||||
int64_t OMXClock::GetTime(bool interpolated)
|
||||
{
|
||||
return CurrentHostCounter() + m_ClockOffset;
|
||||
}
|
||||
|
||||
void OMXClock::CheckSystemClock()
|
||||
{
|
||||
if(!m_systemFrequency)
|
||||
m_systemFrequency = GetFrequency();
|
||||
|
||||
if(!m_systemOffset)
|
||||
m_systemOffset = GetTime();
|
||||
}
|
||||
|
||||
double OMXClock::GetClock(bool interpolated /*= true*/)
|
||||
{
|
||||
Lock();
|
||||
double clock = GetTime(interpolated);
|
||||
UnLock();
|
||||
return SystemToPlaying(clock);
|
||||
}
|
||||
|
||||
double OMXClock::GetClock(double& absolute, bool interpolated /*= true*/)
|
||||
{
|
||||
int64_t current = GetTime(interpolated);
|
||||
|
||||
Lock();
|
||||
CheckSystemClock();
|
||||
absolute = SystemToAbsolute(current);
|
||||
UnLock();
|
||||
|
||||
return SystemToPlaying(current);
|
||||
}
|
||||
|
||||
void OMXClock::SetSpeed(int iSpeed)
|
||||
{
|
||||
// this will sometimes be a little bit of due to rounding errors, ie clock might jump abit when changing speed
|
||||
Lock();
|
||||
|
||||
if(iSpeed == DVD_PLAYSPEED_PAUSE)
|
||||
{
|
||||
if(!m_pauseClock)
|
||||
m_pauseClock = GetTime();
|
||||
UnLock();
|
||||
return;
|
||||
}
|
||||
|
||||
int64_t current;
|
||||
int64_t newfreq = m_systemFrequency * DVD_PLAYSPEED_NORMAL / iSpeed;
|
||||
|
||||
current = GetTime();
|
||||
if( m_pauseClock )
|
||||
{
|
||||
m_startClock += current - m_pauseClock;
|
||||
m_pauseClock = 0;
|
||||
}
|
||||
|
||||
m_startClock = current - (int64_t)((double)(current - m_startClock) * newfreq / m_systemUsed);
|
||||
m_systemUsed = newfreq;
|
||||
UnLock();
|
||||
}
|
||||
|
||||
void OMXClock::Discontinuity(double currentPts)
|
||||
{
|
||||
Lock();
|
||||
m_startClock = GetTime();
|
||||
if(m_pauseClock)
|
||||
m_pauseClock = m_startClock;
|
||||
m_iDisc = currentPts;
|
||||
m_bReset = false;
|
||||
UnLock();
|
||||
}
|
||||
|
||||
void OMXClock::Pause()
|
||||
{
|
||||
Lock();
|
||||
if(!m_pauseClock)
|
||||
m_pauseClock = GetTime();
|
||||
UnLock();
|
||||
}
|
||||
|
||||
void OMXClock::Resume()
|
||||
{
|
||||
Lock();
|
||||
if( m_pauseClock )
|
||||
{
|
||||
int64_t current;
|
||||
current = GetTime();
|
||||
|
||||
m_startClock += current - m_pauseClock;
|
||||
m_pauseClock = 0;
|
||||
}
|
||||
UnLock();
|
||||
}
|
||||
|
||||
bool OMXClock::SetMaxSpeedAdjust(double speed)
|
||||
{
|
||||
Lock();
|
||||
m_maxspeedadjust = speed;
|
||||
UnLock();
|
||||
return m_speedadjust;
|
||||
}
|
||||
|
||||
//returns the refreshrate if the videoreferenceclock is running, -1 otherwise
|
||||
int OMXClock::UpdateFramerate(double fps, double* interval /*= NULL*/)
|
||||
{
|
||||
//sent with fps of 0 means we are not playing video
|
||||
if(fps == 0.0)
|
||||
{
|
||||
Lock();
|
||||
m_speedadjust = false;
|
||||
UnLock();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool OMXClock::OMXReset()
|
||||
{
|
||||
m_iCurrentPts = DVD_NOPTS_VALUE;
|
||||
|
||||
m_video_clock = DVD_NOPTS_VALUE;
|
||||
m_audio_clock = DVD_NOPTS_VALUE;
|
||||
|
||||
if(m_omx_clock.GetComponent() != NULL)
|
||||
{
|
||||
OMX_ERRORTYPE omx_err = OMX_ErrorNone;
|
||||
OMX_TIME_CONFIG_CLOCKSTATETYPE clock;
|
||||
OMX_INIT_STRUCTURE(clock);
|
||||
|
||||
OMXStop();
|
||||
|
||||
clock.eState = OMX_TIME_ClockStateWaitingForStartTime;
|
||||
if(m_has_audio)
|
||||
{
|
||||
clock.nWaitMask |= OMX_CLOCKPORT0;
|
||||
}
|
||||
if(m_has_video)
|
||||
{
|
||||
clock.nWaitMask |= OMX_CLOCKPORT1;
|
||||
clock.nWaitMask |= OMX_CLOCKPORT2;
|
||||
}
|
||||
|
||||
omx_err = OMX_SetConfig(m_omx_clock.GetComponent(), OMX_IndexConfigTimeClockState, &clock);
|
||||
if(omx_err != OMX_ErrorNone)
|
||||
{
|
||||
CLog::Log(LOGERROR, "OMXClock::Reset error setting OMX_IndexConfigTimeClockState\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
OMXStart();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OMXClock::OMXInitialize(bool has_video, bool has_audio)
|
||||
{
|
||||
OMX_ERRORTYPE omx_err = OMX_ErrorNone;
|
||||
CStdString componentName = "";
|
||||
|
||||
m_has_video = has_video;
|
||||
m_has_audio = has_audio;
|
||||
|
||||
componentName = "OMX.broadcom.clock";
|
||||
if(!m_omx_clock.Initialize((const CStdString)componentName, OMX_IndexParamOtherInit))
|
||||
return false;
|
||||
|
||||
OMX_TIME_CONFIG_CLOCKSTATETYPE clock;
|
||||
OMX_INIT_STRUCTURE(clock);
|
||||
|
||||
clock.eState = OMX_TIME_ClockStateWaitingForStartTime;
|
||||
|
||||
if(m_has_audio)
|
||||
{
|
||||
clock.nWaitMask |= OMX_CLOCKPORT0;
|
||||
}
|
||||
if(m_has_video)
|
||||
{
|
||||
clock.nWaitMask |= OMX_CLOCKPORT1;
|
||||
clock.nWaitMask |= OMX_CLOCKPORT2;
|
||||
}
|
||||
|
||||
omx_err = OMX_SetConfig(m_omx_clock.GetComponent(), OMX_IndexConfigTimeClockState, &clock);
|
||||
if(omx_err != OMX_ErrorNone)
|
||||
{
|
||||
CLog::Log(LOGERROR, "OMXClock::Initialize error setting OMX_IndexConfigTimeClockState\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE refClock;
|
||||
OMX_INIT_STRUCTURE(refClock);
|
||||
|
||||
if(m_has_audio)
|
||||
refClock.eClock = OMX_TIME_RefClockAudio;
|
||||
else
|
||||
refClock.eClock = OMX_TIME_RefClockVideo;
|
||||
|
||||
omx_err = OMX_SetConfig(m_omx_clock.GetComponent(), OMX_IndexConfigTimeActiveRefClock, &refClock);
|
||||
if(omx_err != OMX_ErrorNone)
|
||||
{
|
||||
CLog::Log(LOGERROR, "OMXClock::Initialize error setting OMX_IndexConfigTimeCurrentAudioReference\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OMXClock::Deinitialize()
|
||||
{
|
||||
m_omx_clock.Deinitialize();
|
||||
}
|
||||
|
||||
bool OMXClock::OMXStatePause()
|
||||
{
|
||||
if(m_omx_clock.GetComponent() == NULL)
|
||||
return false;
|
||||
|
||||
if(m_omx_clock.GetState() != OMX_StatePause)
|
||||
{
|
||||
OMX_ERRORTYPE omx_err = OMX_ErrorNone;
|
||||
omx_err = m_omx_clock.SetStateForComponent(OMX_StatePause);
|
||||
if (omx_err != OMX_ErrorNone)
|
||||
{
|
||||
CLog::Log(LOGERROR, "OMXClock::StatePause m_omx_clock.SetStateForComponent\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OMXClock::OMXStateExecute()
|
||||
{
|
||||
if(m_omx_clock.GetComponent() == NULL)
|
||||
return false;
|
||||
|
||||
if(m_omx_clock.GetState() != OMX_StateExecuting)
|
||||
{
|
||||
OMX_ERRORTYPE omx_err = OMX_ErrorNone;
|
||||
omx_err = m_omx_clock.SetStateForComponent(OMX_StateExecuting);
|
||||
if (omx_err != OMX_ErrorNone)
|
||||
{
|
||||
CLog::Log(LOGERROR, "OMXClock::StateExecute m_omx_clock.SetStateForComponent\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OMXClock::OMXStateIdle()
|
||||
{
|
||||
if(m_omx_clock.GetComponent() == NULL)
|
||||
return;
|
||||
|
||||
if(m_omx_clock.GetState() == OMX_StateExecuting)
|
||||
m_omx_clock.SetStateForComponent(OMX_StatePause);
|
||||
|
||||
if(m_omx_clock.GetState() != OMX_StateIdle)
|
||||
m_omx_clock.SetStateForComponent(OMX_StateIdle);
|
||||
}
|
||||
|
||||
COMXCoreComponent *OMXClock::GetOMXClock()
|
||||
{
|
||||
if(!m_omx_clock.GetComponent())
|
||||
return NULL;
|
||||
|
||||
return &m_omx_clock;
|
||||
}
|
||||
|
||||
bool OMXClock::OMXStop()
|
||||
{
|
||||
if(m_omx_clock.GetComponent() == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
OMX_ERRORTYPE omx_err = OMX_ErrorNone;
|
||||
OMX_TIME_CONFIG_CLOCKSTATETYPE clock;
|
||||
OMX_INIT_STRUCTURE(clock);
|
||||
|
||||
clock.eState = OMX_TIME_ClockStateStopped;
|
||||
|
||||
omx_err = OMX_SetConfig(m_omx_clock.GetComponent(), OMX_IndexConfigTimeClockState, &clock);
|
||||
if(omx_err != OMX_ErrorNone)
|
||||
{
|
||||
CLog::Log(LOGERROR, "OMXClock::Stop error setting OMX_IndexConfigTimeClockState\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OMXClock::OMXStart()
|
||||
{
|
||||
if(m_omx_clock.GetComponent() == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
OMX_ERRORTYPE omx_err = OMX_ErrorNone;
|
||||
OMX_TIME_CONFIG_CLOCKSTATETYPE clock;
|
||||
OMX_INIT_STRUCTURE(clock);
|
||||
|
||||
clock.eState = OMX_TIME_ClockStateRunning;
|
||||
|
||||
omx_err = OMX_SetConfig(m_omx_clock.GetComponent(), OMX_IndexConfigTimeClockState, &clock);
|
||||
if(omx_err != OMX_ErrorNone)
|
||||
{
|
||||
CLog::Log(LOGERROR, "OMXClock::Start error setting OMX_IndexConfigTimeClockState\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OMXClock::OMXPause()
|
||||
{
|
||||
if(m_omx_clock.GetComponent() == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(m_pause)
|
||||
return true;
|
||||
|
||||
OMX_ERRORTYPE omx_err = OMX_ErrorNone;
|
||||
OMX_TIME_CONFIG_SCALETYPE scaleType;
|
||||
OMX_INIT_STRUCTURE(scaleType);
|
||||
|
||||
scaleType.xScale = 0; // pause
|
||||
|
||||
omx_err = OMX_SetConfig(m_omx_clock.GetComponent(), OMX_IndexConfigTimeScale, &scaleType);
|
||||
if(omx_err != OMX_ErrorNone)
|
||||
{
|
||||
CLog::Log(LOGERROR, "OMXClock::Pause error setting OMX_IndexConfigTimeClockState\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pause = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OMXClock::OMXResume()
|
||||
{
|
||||
if(m_omx_clock.GetComponent() == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!m_pause)
|
||||
return true;
|
||||
|
||||
OMX_ERRORTYPE omx_err = OMX_ErrorNone;
|
||||
OMX_TIME_CONFIG_SCALETYPE scaleType;
|
||||
OMX_INIT_STRUCTURE(scaleType);
|
||||
|
||||
scaleType.xScale = (1<<16); // normal speed
|
||||
|
||||
omx_err = OMX_SetConfig(m_omx_clock.GetComponent(), OMX_IndexConfigTimeScale, &scaleType);
|
||||
if(omx_err != OMX_ErrorNone)
|
||||
{
|
||||
CLog::Log(LOGERROR, "OMXClock::Resume error setting OMX_IndexConfigTimeClockState\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pause = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OMXClock::OMXWaitStart(double pts)
|
||||
{
|
||||
if(m_omx_clock.GetComponent() == NULL)
|
||||
return false;
|
||||
|
||||
OMX_ERRORTYPE omx_err = OMX_ErrorNone;
|
||||
OMX_TIME_CONFIG_CLOCKSTATETYPE clock;
|
||||
OMX_INIT_STRUCTURE(clock);
|
||||
|
||||
if(pts == DVD_NOPTS_VALUE)
|
||||
pts = 0;
|
||||
|
||||
clock.nStartTime = ToOMXTime((uint64_t)pts);
|
||||
|
||||
if(pts == DVD_NOPTS_VALUE)
|
||||
{
|
||||
clock.eState = OMX_TIME_ClockStateRunning;
|
||||
clock.nWaitMask = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
clock.eState = OMX_TIME_ClockStateWaitingForStartTime;
|
||||
|
||||
if(m_has_audio)
|
||||
{
|
||||
clock.nWaitMask |= OMX_CLOCKPORT0;
|
||||
}
|
||||
if(m_has_video)
|
||||
{
|
||||
clock.nWaitMask |= OMX_CLOCKPORT1;
|
||||
clock.nWaitMask |= OMX_CLOCKPORT2;
|
||||
}
|
||||
}
|
||||
|
||||
omx_err = OMX_SetConfig(m_omx_clock.GetComponent(), OMX_IndexConfigTimeClockState, &clock);
|
||||
if(omx_err != OMX_ErrorNone)
|
||||
{
|
||||
CLog::Log(LOGERROR, "OMXClock::Initialize error setting OMX_IndexConfigTimeClockState\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OMXClock::OMXSpeed(int speed)
|
||||
{
|
||||
if(m_omx_clock.GetComponent() == NULL)
|
||||
return false;
|
||||
|
||||
OMX_ERRORTYPE omx_err = OMX_ErrorNone;
|
||||
OMX_TIME_CONFIG_SCALETYPE scaleType;
|
||||
OMX_INIT_STRUCTURE(scaleType);
|
||||
|
||||
scaleType.xScale = (speed << 16);
|
||||
|
||||
m_play_speed = speed;
|
||||
|
||||
omx_err = OMX_SetConfig(m_omx_clock.GetComponent(), OMX_IndexConfigTimeScale, &scaleType);
|
||||
if(omx_err != OMX_ErrorNone)
|
||||
{
|
||||
CLog::Log(LOGERROR, "OMXClock::Speed error setting OMX_IndexConfigTimeClockState\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OMXClock::AddTimespecs(struct timespec &time, long millisecs)
|
||||
{
|
||||
time.tv_sec += millisecs / 1000;
|
||||
time.tv_nsec += (millisecs % 1000) * 1000000;
|
||||
if (time.tv_nsec > 1000000000)
|
||||
{
|
||||
time.tv_sec += 1;
|
||||
time.tv_nsec -= 1000000000;
|
||||
}
|
||||
}
|
||||
|
||||
double OMXClock::GetPTS()
|
||||
{
|
||||
Lock();
|
||||
double pts = m_iCurrentPts;
|
||||
UnLock();
|
||||
return pts;
|
||||
}
|
||||
|
||||
void OMXClock::SetPTS(double pts)
|
||||
{
|
||||
Lock();
|
||||
m_iCurrentPts = pts;
|
||||
UnLock();
|
||||
};
|
||||
|
||||
bool OMXClock::HDMIClockSync()
|
||||
{
|
||||
if(m_omx_clock.GetComponent() == NULL)
|
||||
return false;
|
||||
|
||||
|
||||
OMX_ERRORTYPE omx_err = OMX_ErrorNone;
|
||||
OMX_CONFIG_LATENCYTARGETTYPE latencyTarget;
|
||||
OMX_INIT_STRUCTURE(latencyTarget);
|
||||
|
||||
latencyTarget.nPortIndex = OMX_ALL;
|
||||
latencyTarget.bEnabled = OMX_TRUE;
|
||||
latencyTarget.nFilter = 10;
|
||||
latencyTarget.nTarget = 0;
|
||||
latencyTarget.nShift = 3;
|
||||
latencyTarget.nSpeedFactor = -200;
|
||||
latencyTarget.nInterFactor = 100;
|
||||
latencyTarget.nAdjCap = 100;
|
||||
|
||||
omx_err = OMX_SetConfig(m_omx_clock.GetComponent(), OMX_IndexConfigLatencyTarget, &latencyTarget);
|
||||
if(omx_err != OMX_ErrorNone)
|
||||
{
|
||||
CLog::Log(LOGERROR, "OMXClock::Speed error setting OMX_IndexConfigLatencyTarget\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int64_t OMXClock::CurrentHostCounter(void)
|
||||
{
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
return( ((int64_t)now.tv_sec * 1000000000L) + now.tv_nsec );
|
||||
}
|
||||
|
||||
int64_t OMXClock::CurrentHostFrequency(void)
|
||||
{
|
||||
return( (int64_t)1000000000L );
|
||||
}
|
||||
|
||||
void OMXClock::AddTimeSpecNano(struct timespec &time, uint64_t nanoseconds)
|
||||
{
|
||||
time.tv_sec += nanoseconds / 1000000000;
|
||||
time.tv_nsec += (nanoseconds % 1000000000);
|
||||
if (time.tv_nsec > 1000000000)
|
||||
{
|
||||
time.tv_sec += 1;
|
||||
time.tv_nsec -= 1000000000;
|
||||
}
|
||||
}
|
||||
|
||||
void OMXClock::OMXSleep(unsigned int dwMilliSeconds)
|
||||
{
|
||||
struct timespec req;
|
||||
req.tv_sec = dwMilliSeconds / 1000;
|
||||
req.tv_nsec = (dwMilliSeconds % 1000) * 1000000;
|
||||
|
||||
while ( nanosleep(&req, &req) == -1 && errno == EINTR && (req.tv_nsec > 0 || req.tv_sec > 0));
|
||||
}
|
||||
|
||||
int OMXClock::GetRefreshRate(double* interval)
|
||||
{
|
||||
if(!interval)
|
||||
return false;
|
||||
|
||||
*interval = m_fps;
|
||||
return true;
|
||||
}
|
||||
156
OMXClock.h
Normal file
156
OMXClock.h
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _AVCLOCK_H_
|
||||
#define _AVCLOCK_H_
|
||||
|
||||
#include "DllAvFormat.h"
|
||||
|
||||
#include "OMXCore.h"
|
||||
|
||||
#define AV_SYNC_THRESHOLD 0.01
|
||||
#define AV_NOSYNC_THRESHOLD 10.0
|
||||
#define SAMPLE_CORRECTION_PERCENT_MAX 10
|
||||
#define AUDIO_DIFF_AVG_NB 20
|
||||
|
||||
#define DVD_TIME_BASE 1000000
|
||||
#define DVD_NOPTS_VALUE (-1LL<<52) // should be possible to represent in both double and __int64
|
||||
|
||||
#define DVD_TIME_TO_SEC(x) ((int)((double)(x) / DVD_TIME_BASE))
|
||||
#define DVD_TIME_TO_MSEC(x) ((int)((double)(x) * 1000 / DVD_TIME_BASE))
|
||||
#define DVD_SEC_TO_TIME(x) ((double)(x) * DVD_TIME_BASE)
|
||||
#define DVD_MSEC_TO_TIME(x) ((double)(x) * DVD_TIME_BASE / 1000)
|
||||
|
||||
#define DVD_PLAYSPEED_PAUSE 0 // frame stepping
|
||||
#define DVD_PLAYSPEED_NORMAL 1000
|
||||
|
||||
#ifdef OMX_SKIP64BIT
|
||||
static inline OMX_TICKS ToOMXTime(int64_t pts)
|
||||
{
|
||||
OMX_TICKS ticks;
|
||||
ticks.nLowPart = pts;
|
||||
ticks.nHighPart = pts >> 32;
|
||||
return ticks;
|
||||
}
|
||||
static inline uint64_t FromOMXTime(OMX_TICKS ticks)
|
||||
{
|
||||
uint64_t pts = ticks.nLowPart | ((uint64_t)ticks.nHighPart << 32);
|
||||
return pts;
|
||||
}
|
||||
#else
|
||||
#define FromOMXTime(x) (x)
|
||||
#define ToOMXTime(x) (x)
|
||||
#endif
|
||||
|
||||
enum {
|
||||
AV_SYNC_AUDIO_MASTER,
|
||||
AV_SYNC_VIDEO_MASTER,
|
||||
AV_SYNC_EXTERNAL_MASTER,
|
||||
};
|
||||
|
||||
class OMXClock
|
||||
{
|
||||
protected:
|
||||
double m_video_clock;
|
||||
double m_audio_clock;
|
||||
bool m_pause;
|
||||
double m_iCurrentPts;
|
||||
bool m_has_video;
|
||||
bool m_has_audio;
|
||||
int m_play_speed;
|
||||
pthread_mutex_t m_lock;
|
||||
void CheckSystemClock();
|
||||
double SystemToAbsolute(int64_t system);
|
||||
double SystemToPlaying(int64_t system);
|
||||
int64_t m_systemUsed;
|
||||
int64_t m_startClock;
|
||||
int64_t m_pauseClock;
|
||||
double m_iDisc;
|
||||
bool m_bReset;
|
||||
static int64_t m_systemFrequency;
|
||||
static int64_t m_systemOffset;
|
||||
int64_t m_ClockOffset;
|
||||
double m_maxspeedadjust;
|
||||
bool m_speedadjust;
|
||||
static bool m_ismasterclock;
|
||||
double m_fps;
|
||||
private:
|
||||
COMXCoreComponent m_omx_clock;
|
||||
DllAvFormat m_dllAvFormat;
|
||||
public:
|
||||
OMXClock();
|
||||
~OMXClock();
|
||||
void Lock();
|
||||
void UnLock();
|
||||
int64_t GetFrequency();
|
||||
int64_t GetTime(bool interpolated = true);
|
||||
double GetAbsoluteClock(bool interpolated = true);
|
||||
int64_t Wait(int64_t Target);
|
||||
double WaitAbsoluteClock(double target);
|
||||
double GetClock(bool interpolated = true);
|
||||
double GetClock(double& absolute, bool interpolated = true);
|
||||
void SetSpeed(int iSpeed);
|
||||
void SetMasterClock(bool ismasterclock) { m_ismasterclock = ismasterclock; }
|
||||
bool IsMasterClock() { return m_ismasterclock; }
|
||||
void Discontinuity(double currentPts = 0LL);
|
||||
|
||||
void Reset() { m_bReset = true; }
|
||||
void Pause();
|
||||
void Resume();
|
||||
|
||||
int UpdateFramerate(double fps, double* interval = NULL);
|
||||
bool SetMaxSpeedAdjust(double speed);
|
||||
|
||||
bool OMXReset();
|
||||
bool OMXInitialize(bool has_video, bool has_audio);
|
||||
void Deinitialize();
|
||||
bool OMXIsPaused() { return m_pause; };
|
||||
bool OMXStop();
|
||||
bool OMXStart();
|
||||
bool OMXPause();
|
||||
bool OMXResume();
|
||||
bool OMXWaitStart(double pts);
|
||||
bool OMXSpeed(int speed);
|
||||
int OMXPlaySpeed() { return m_play_speed; };
|
||||
COMXCoreComponent *GetOMXClock();
|
||||
bool OMXStatePause();
|
||||
bool OMXStateExecute();
|
||||
void OMXStateIdle();
|
||||
double GetPTS();
|
||||
void SetPTS(double pts);
|
||||
static void AddTimespecs(struct timespec &time, long millisecs);
|
||||
bool HDMIClockSync();
|
||||
static int64_t CurrentHostCounter(void);
|
||||
static int64_t CurrentHostFrequency(void);
|
||||
void SetVideoClock(double video_clock) { m_video_clock = video_clock; };
|
||||
void SetAudioClock(double audio_clock) { m_audio_clock = audio_clock; };
|
||||
double GetVideoClock() { return m_video_clock; };
|
||||
double GetAudioClock() { return m_audio_clock; };
|
||||
bool HasVideo() { return m_has_video; };
|
||||
bool HasAudio() { return m_has_audio; };
|
||||
static void AddTimeSpecNano(struct timespec &time, uint64_t nanoseconds);
|
||||
static void OMXSleep(unsigned int dwMilliSeconds);
|
||||
|
||||
int GetRefreshRate(double* interval = NULL);
|
||||
void SetRefreshRate(double fps) { m_fps = fps; };
|
||||
};
|
||||
|
||||
#endif
|
||||
1642
OMXCore.cpp
Normal file
1642
OMXCore.cpp
Normal file
File diff suppressed because it is too large
Load diff
216
OMXCore.h
Normal file
216
OMXCore.h
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
#pragma once
|
||||
/*
|
||||
* Copyright (C) 2010 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(HAVE_OMXLIB)
|
||||
|
||||
#include "utils/StdString.h"
|
||||
|
||||
#include <queue>
|
||||
|
||||
// TODO: should this be in configure
|
||||
#ifndef OMX_SKIP64BIT
|
||||
#define OMX_SKIP64BIT
|
||||
#endif
|
||||
|
||||
#include "DllOMX.h"
|
||||
|
||||
#include <semaphore.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// debug spew defines
|
||||
#if 0
|
||||
#define OMX_DEBUG_VERBOSE
|
||||
#define OMX_DEBUG_EVENTHANDLER
|
||||
#endif
|
||||
|
||||
#define OMX_INIT_STRUCTURE(a) \
|
||||
memset(&(a), 0, sizeof(a)); \
|
||||
(a).nSize = sizeof(a); \
|
||||
(a).nVersion.s.nVersionMajor = OMX_VERSION_MAJOR; \
|
||||
(a).nVersion.s.nVersionMinor = OMX_VERSION_MINOR; \
|
||||
(a).nVersion.s.nRevision = OMX_VERSION_REVISION; \
|
||||
(a).nVersion.s.nStep = OMX_VERSION_STEP
|
||||
|
||||
#include "DllAvFormat.h"
|
||||
|
||||
#define OMX_MAX_PORTS 10
|
||||
|
||||
typedef struct omx_event {
|
||||
OMX_EVENTTYPE eEvent;
|
||||
OMX_U32 nData1;
|
||||
OMX_U32 nData2;
|
||||
} omx_event;
|
||||
|
||||
class DllLibOMXCore;
|
||||
class COMXCore;
|
||||
class COMXCoreComponent;
|
||||
class COMXCoreTunel;
|
||||
class COMXCoreClock;
|
||||
|
||||
class COMXCoreTunel
|
||||
{
|
||||
public:
|
||||
COMXCoreTunel();
|
||||
~COMXCoreTunel();
|
||||
|
||||
void Initialize(COMXCoreComponent *src_component, unsigned int src_port, COMXCoreComponent *dst_component, unsigned int dst_port);
|
||||
OMX_ERRORTYPE Flush();
|
||||
OMX_ERRORTYPE Deestablish(bool noWait = false);
|
||||
OMX_ERRORTYPE Establish(bool portSettingsChanged);
|
||||
private:
|
||||
bool m_portSettingsChanged;
|
||||
COMXCoreComponent *m_src_component;
|
||||
COMXCoreComponent *m_dst_component;
|
||||
unsigned int m_src_port;
|
||||
unsigned int m_dst_port;
|
||||
DllOMX *m_DllOMX;
|
||||
bool m_DllOMXOpen;
|
||||
};
|
||||
|
||||
class COMXCoreComponent
|
||||
{
|
||||
public:
|
||||
COMXCoreComponent();
|
||||
~COMXCoreComponent();
|
||||
|
||||
OMX_HANDLETYPE GetComponent() { return m_handle; };
|
||||
unsigned int GetInputPort() { return m_input_port; };
|
||||
unsigned int GetOutputPort() { return m_output_port; };
|
||||
CStdString GetName() { return m_componentName; };
|
||||
|
||||
OMX_ERRORTYPE DisableAllPorts();
|
||||
void Remove(OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2);
|
||||
OMX_ERRORTYPE AddEvent(OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2);
|
||||
//bool GotError(OMX_ERRORTYPE errorType);
|
||||
OMX_ERRORTYPE WaitForEvent(OMX_EVENTTYPE event, long timeout = 300);
|
||||
OMX_ERRORTYPE WaitForCommand(OMX_U32 command, OMX_U32 nData2, long timeout = 2000);
|
||||
OMX_ERRORTYPE SetStateForComponent(OMX_STATETYPE state);
|
||||
OMX_STATETYPE GetState();
|
||||
OMX_ERRORTYPE SetParameter(OMX_INDEXTYPE paramIndex, OMX_PTR paramStruct);
|
||||
OMX_ERRORTYPE GetParameter(OMX_INDEXTYPE paramIndex, OMX_PTR paramStruct);
|
||||
OMX_ERRORTYPE SetConfig(OMX_INDEXTYPE configIndex, OMX_PTR configStruct);
|
||||
OMX_ERRORTYPE GetConfig(OMX_INDEXTYPE configIndex, OMX_PTR configStruct);
|
||||
OMX_ERRORTYPE SendCommand(OMX_COMMANDTYPE cmd, OMX_U32 cmdParam, OMX_PTR cmdParamData);
|
||||
OMX_ERRORTYPE EnablePort(unsigned int port, bool wait = true);
|
||||
OMX_ERRORTYPE DisablePort(unsigned int port, bool wait = true);
|
||||
OMX_ERRORTYPE UseEGLImage(OMX_BUFFERHEADERTYPE** ppBufferHdr, OMX_U32 nPortIndex, OMX_PTR pAppPrivate, void* eglImage);
|
||||
|
||||
bool Initialize( const CStdString &component_name, OMX_INDEXTYPE index);
|
||||
bool Deinitialize();
|
||||
|
||||
// OMXCore Decoder delegate callback routines.
|
||||
static OMX_ERRORTYPE DecoderEventHandlerCallback(OMX_HANDLETYPE hComponent, OMX_PTR pAppData,
|
||||
OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2, OMX_PTR pEventData);
|
||||
static OMX_ERRORTYPE DecoderEmptyBufferDoneCallback(
|
||||
OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBuffer);
|
||||
static OMX_ERRORTYPE DecoderFillBufferDoneCallback(
|
||||
OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBufferHeader);
|
||||
|
||||
// OMXCore decoder callback routines.
|
||||
OMX_ERRORTYPE DecoderEventHandler(OMX_HANDLETYPE hComponent, OMX_PTR pAppData,
|
||||
OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2, OMX_PTR pEventData);
|
||||
OMX_ERRORTYPE DecoderEmptyBufferDone(
|
||||
OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBuffer);
|
||||
OMX_ERRORTYPE DecoderFillBufferDone(
|
||||
OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBuffer);
|
||||
|
||||
OMX_ERRORTYPE EmptyThisBuffer(OMX_BUFFERHEADERTYPE *omx_buffer);
|
||||
OMX_ERRORTYPE FillThisBuffer(OMX_BUFFERHEADERTYPE *omx_buffer);
|
||||
OMX_ERRORTYPE FreeOutputBuffer(OMX_BUFFERHEADERTYPE *omx_buffer);
|
||||
|
||||
unsigned int GetInputBufferSize();
|
||||
unsigned int GetOutputBufferSize();
|
||||
|
||||
unsigned int GetInputBufferSpace();
|
||||
unsigned int GetOutputBufferSpace();
|
||||
|
||||
void FlushAll();
|
||||
void FlushInput();
|
||||
void FlushOutput();
|
||||
|
||||
OMX_BUFFERHEADERTYPE *GetInputBuffer(long timeout=200);
|
||||
OMX_BUFFERHEADERTYPE *GetOutputBuffer(long timeout=200);
|
||||
|
||||
OMX_ERRORTYPE AllocInputBuffers(void);
|
||||
OMX_ERRORTYPE AllocOutputBuffers(void);
|
||||
|
||||
OMX_ERRORTYPE FreeInputBuffers(bool wait);
|
||||
OMX_ERRORTYPE FreeOutputBuffers(bool wait);
|
||||
|
||||
bool IsEOS() { return m_eos; };
|
||||
|
||||
private:
|
||||
OMX_HANDLETYPE m_handle;
|
||||
unsigned int m_input_port;
|
||||
unsigned int m_output_port;
|
||||
int m_ports_enabled[OMX_MAX_PORTS];
|
||||
CStdString m_componentName;
|
||||
pthread_mutex_t m_omx_event_mutex;
|
||||
std::vector<omx_event> m_omx_events;
|
||||
|
||||
OMX_CALLBACKTYPE m_callbacks;
|
||||
|
||||
// OMXCore input buffers (demuxer packets)
|
||||
pthread_mutex_t m_omx_input_mutex;
|
||||
std::queue<OMX_BUFFERHEADERTYPE*> m_omx_input_avaliable;
|
||||
std::vector<OMX_BUFFERHEADERTYPE*> m_omx_input_buffers;
|
||||
unsigned int m_input_alignment;
|
||||
unsigned int m_input_buffer_size;
|
||||
unsigned int m_input_buffer_count;
|
||||
|
||||
// OMXCore output buffers (video frames)
|
||||
pthread_mutex_t m_omx_output_mutex;
|
||||
std::queue<OMX_BUFFERHEADERTYPE*> m_omx_output_avaliable;
|
||||
std::vector<OMX_BUFFERHEADERTYPE*> m_omx_output_buffers;
|
||||
unsigned int m_output_alignment;
|
||||
unsigned int m_output_buffer_size;
|
||||
unsigned int m_output_buffer_count;
|
||||
|
||||
bool m_exit;
|
||||
DllOMX *m_DllOMX;
|
||||
bool m_DllOMXOpen;
|
||||
pthread_cond_t m_input_buffer_cond;
|
||||
pthread_cond_t m_output_buffer_cond;
|
||||
pthread_cond_t m_omx_event_cond;
|
||||
bool m_eos;
|
||||
bool m_flush_input;
|
||||
bool m_flush_output;
|
||||
};
|
||||
|
||||
class COMXCore
|
||||
{
|
||||
public:
|
||||
COMXCore();
|
||||
~COMXCore();
|
||||
|
||||
// initialize OMXCore and get decoder component
|
||||
bool Initialize();
|
||||
void Deinitialize();
|
||||
|
||||
protected:
|
||||
bool m_is_open;
|
||||
bool m_Initialized;
|
||||
DllOMX *m_DllOMX;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
78
OMXOverlay.h
Normal file
78
OMXOverlay.h
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <vector>
|
||||
|
||||
enum OMXOverlayType
|
||||
{
|
||||
OMXOVERLAY_TYPE_NONE = -1,
|
||||
OMXOVERLAY_TYPE_SPU = 1,
|
||||
OMXOVERLAY_TYPE_TEXT = 2,
|
||||
OMXOVERLAY_TYPE_IMAGE = 3,
|
||||
OMXOVERLAY_TYPE_SSA = 4
|
||||
};
|
||||
|
||||
class COMXOverlay
|
||||
{
|
||||
public:
|
||||
COMXOverlay(OMXOverlayType type)
|
||||
{
|
||||
m_type = type;
|
||||
|
||||
iPTSStartTime = 0LL;
|
||||
iPTSStopTime = 0LL;
|
||||
bForced = false;
|
||||
replace = false;
|
||||
|
||||
iGroupId = 0;
|
||||
}
|
||||
|
||||
COMXOverlay(const COMXOverlay& src)
|
||||
{
|
||||
m_type = src.m_type;
|
||||
iPTSStartTime = src.iPTSStartTime;
|
||||
iPTSStopTime = src.iPTSStopTime;
|
||||
bForced = src.bForced;
|
||||
replace = src.replace;
|
||||
iGroupId = src.iGroupId;
|
||||
}
|
||||
|
||||
virtual ~COMXOverlay()
|
||||
{
|
||||
}
|
||||
|
||||
bool IsOverlayType(OMXOverlayType type) { return (m_type == type); }
|
||||
|
||||
double iPTSStartTime;
|
||||
double iPTSStopTime;
|
||||
bool bForced; // display, no matter what
|
||||
bool replace; // replace by next nomatter what stoptime it has
|
||||
int iGroupId;
|
||||
protected:
|
||||
OMXOverlayType m_type;
|
||||
};
|
||||
|
||||
typedef std::vector<COMXOverlay*> VecOMXOverlays;
|
||||
typedef std::vector<COMXOverlay*>::iterator VecOMXOverlaysIter;
|
||||
88
OMXOverlayCodec.h
Normal file
88
OMXOverlayCodec.h
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "OMXOverlay.h"
|
||||
#include "PlatformDefs.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
// VC_ messages, messages can be combined
|
||||
#define OC_ERROR 0x00000001 // an error occured, no other messages will be returned
|
||||
#define OC_BUFFER 0x00000002 // the decoder needs more data
|
||||
#define OC_OVERLAY 0x00000004 // the decoder decoded an overlay, call Decode(NULL, 0) again to parse the rest of the data
|
||||
|
||||
class COMXStreamInfo;
|
||||
|
||||
class COMXOverlayCodec
|
||||
{
|
||||
public:
|
||||
|
||||
COMXOverlayCodec(const char* name)
|
||||
{
|
||||
m_codecName = name;
|
||||
}
|
||||
|
||||
virtual ~COMXOverlayCodec() {}
|
||||
|
||||
/*
|
||||
* Open the decoder, returns true on success
|
||||
*/
|
||||
virtual bool Open(COMXStreamInfo &hints) = 0;
|
||||
|
||||
/*
|
||||
* Dispose, Free all resources
|
||||
*/
|
||||
virtual void Dispose() = 0;
|
||||
|
||||
/*
|
||||
* returns one or a combination of VC_ messages
|
||||
* pData and iSize can be NULL, this means we should flush the rest of the data.
|
||||
*/
|
||||
virtual int Decode(BYTE* data, int size, double pts, double duration) = 0;
|
||||
|
||||
/*
|
||||
* Reset the decoder.
|
||||
* Should be the same as calling Dispose and Open after each other
|
||||
*/
|
||||
virtual void Reset() = 0;
|
||||
|
||||
/*
|
||||
* Flush the current working packet
|
||||
* This may leave the internal state intact
|
||||
*/
|
||||
virtual void Flush() = 0;
|
||||
|
||||
/*
|
||||
* returns a valid overlay or NULL
|
||||
* the data is valid until the next Decode call
|
||||
*/
|
||||
virtual COMXOverlay* GetOverlay() = 0;
|
||||
|
||||
/*
|
||||
* return codecs name
|
||||
*/
|
||||
virtual const char* GetName() { return m_codecName.c_str(); }
|
||||
|
||||
private:
|
||||
std::string m_codecName;
|
||||
};
|
||||
152
OMXOverlayCodecText.cpp
Normal file
152
OMXOverlayCodecText.cpp
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
#include "OMXOverlayCodecText.h"
|
||||
#include "OMXOverlayText.h"
|
||||
#include "OMXStreamInfo.h"
|
||||
#include "utils/log.h"
|
||||
#include "OMXSubtitleTagSami.h"
|
||||
|
||||
COMXOverlayCodecText::COMXOverlayCodecText() : COMXOverlayCodec("Text Subtitle Decoder")
|
||||
{
|
||||
m_pOverlay = NULL;
|
||||
m_bIsSSA = false;
|
||||
}
|
||||
|
||||
COMXOverlayCodecText::~COMXOverlayCodecText()
|
||||
{
|
||||
if(m_pOverlay)
|
||||
delete m_pOverlay;
|
||||
m_pOverlay = NULL;
|
||||
}
|
||||
|
||||
bool COMXOverlayCodecText::Open(COMXStreamInfo &hints)
|
||||
{
|
||||
m_bIsSSA = (hints.codec == CODEC_ID_SSA);
|
||||
if(hints.codec == CODEC_ID_TEXT || hints.codec == CODEC_ID_SSA)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void COMXOverlayCodecText::Dispose()
|
||||
{
|
||||
if(m_pOverlay)
|
||||
delete m_pOverlay;
|
||||
m_pOverlay = NULL;
|
||||
}
|
||||
|
||||
int COMXOverlayCodecText::Decode(BYTE* data, int size, double pts, double duration)
|
||||
{
|
||||
if(m_pOverlay)
|
||||
delete m_pOverlay;
|
||||
m_pOverlay = NULL;
|
||||
|
||||
m_pOverlay = new COMXOverlayText();
|
||||
m_pOverlay->iPTSStartTime = 0;
|
||||
m_pOverlay->iPTSStopTime = 0;
|
||||
|
||||
|
||||
char *start, *end, *p;
|
||||
start = (char*)data;
|
||||
end = (char*)data + size;
|
||||
p = (char*)data;
|
||||
|
||||
if (m_bIsSSA)
|
||||
{
|
||||
// currently just skip the prefixed ssa fields (8 fields)
|
||||
int nFieldCount = 8;
|
||||
while (nFieldCount > 0 && start < end)
|
||||
{
|
||||
if (*start == ',')
|
||||
nFieldCount--;
|
||||
|
||||
start++;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
COMXSubtitleTagSami TagConv;
|
||||
bool Taginit = TagConv.Init();
|
||||
|
||||
while(p<end)
|
||||
{
|
||||
if(*p == '{')
|
||||
{
|
||||
if(p>start)
|
||||
{
|
||||
if(Taginit)
|
||||
TagConv.ConvertLine(m_pOverlay, start, p-start);
|
||||
else
|
||||
m_pOverlay->AddElement(new COMXOverlayText::CElementText(start, p-start));
|
||||
}
|
||||
start = p+1;
|
||||
|
||||
while(*p != '}' && p<end)
|
||||
p++;
|
||||
|
||||
char* override = (char*)malloc(p-start + 1);
|
||||
memcpy(override, start, p-start);
|
||||
override[p-start] = '\0';
|
||||
CLog::Log(LOGINFO, "%s - Skipped formatting tag %s", __FUNCTION__, override);
|
||||
free(override);
|
||||
|
||||
start = p+1;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
if(p>start)
|
||||
{
|
||||
if(Taginit)
|
||||
{
|
||||
TagConv.ConvertLine(m_pOverlay, start, p-start);
|
||||
TagConv.CloseTag(m_pOverlay);
|
||||
}
|
||||
else
|
||||
m_pOverlay->AddElement(new COMXOverlayText::CElementText(start, p-start));
|
||||
}
|
||||
return OC_OVERLAY;
|
||||
}
|
||||
|
||||
void COMXOverlayCodecText::Reset()
|
||||
{
|
||||
if(m_pOverlay)
|
||||
delete m_pOverlay;
|
||||
m_pOverlay = NULL;
|
||||
}
|
||||
|
||||
void COMXOverlayCodecText::Flush()
|
||||
{
|
||||
if(m_pOverlay)
|
||||
delete m_pOverlay;
|
||||
m_pOverlay = NULL;
|
||||
}
|
||||
|
||||
COMXOverlay* COMXOverlayCodecText::GetOverlay()
|
||||
{
|
||||
if(m_pOverlay)
|
||||
{
|
||||
COMXOverlay* overlay = m_pOverlay;
|
||||
m_pOverlay = NULL;
|
||||
return overlay;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
43
OMXOverlayCodecText.h
Normal file
43
OMXOverlayCodecText.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "OMXOverlayCodec.h"
|
||||
|
||||
class COMXOverlayText;
|
||||
|
||||
class COMXOverlayCodecText : public COMXOverlayCodec
|
||||
{
|
||||
public:
|
||||
COMXOverlayCodecText();
|
||||
virtual ~COMXOverlayCodecText();
|
||||
virtual bool Open(COMXStreamInfo &hints);
|
||||
virtual void Dispose();
|
||||
virtual int Decode(BYTE* data, int size, double pts, double duration);
|
||||
virtual void Reset();
|
||||
virtual void Flush();
|
||||
virtual COMXOverlay* GetOverlay();
|
||||
|
||||
private:
|
||||
bool m_bIsSSA;
|
||||
COMXOverlayText* m_pOverlay;
|
||||
};
|
||||
129
OMXOverlayText.h
Normal file
129
OMXOverlayText.h
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "OMXOverlay.h"
|
||||
#include <string.h>
|
||||
|
||||
class COMXOverlayText : public COMXOverlay
|
||||
{
|
||||
public:
|
||||
|
||||
enum ElementType
|
||||
{
|
||||
ELEMENT_TYPE_NONE = -1,
|
||||
ELEMENT_TYPE_TEXT = 1,
|
||||
ELEMENT_TYPE_PROPERTY = 2
|
||||
};
|
||||
|
||||
class CElement
|
||||
{
|
||||
public:
|
||||
CElement(ElementType type)
|
||||
{
|
||||
m_type = type;
|
||||
}
|
||||
|
||||
virtual ~CElement()
|
||||
{
|
||||
}
|
||||
|
||||
bool IsElementType(ElementType type) { return (type == m_type); }
|
||||
|
||||
CElement* pNext;
|
||||
ElementType m_type;
|
||||
};
|
||||
|
||||
class CElementText : public CElement
|
||||
{
|
||||
public:
|
||||
CElementText(const char* strText, int size = -1) : CElement(ELEMENT_TYPE_TEXT)
|
||||
{
|
||||
if(size == -1)
|
||||
m_text = strdup(strText);
|
||||
else
|
||||
{
|
||||
m_text = (char*)malloc(size+1);
|
||||
memcpy(m_text, strText, size);
|
||||
m_text[size] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~CElementText()
|
||||
{
|
||||
if (m_text) free(m_text);
|
||||
}
|
||||
|
||||
char* m_text;
|
||||
};
|
||||
|
||||
class CElementProperty : public CElement
|
||||
{
|
||||
CElementProperty() : CElement(ELEMENT_TYPE_PROPERTY)
|
||||
{
|
||||
bItalic = false;
|
||||
bBold = false;
|
||||
}
|
||||
|
||||
public:
|
||||
bool bItalic;
|
||||
bool bBold;
|
||||
// color
|
||||
};
|
||||
|
||||
COMXOverlayText() : COMXOverlay(OMXOVERLAY_TYPE_TEXT)
|
||||
{
|
||||
m_pHead = NULL;
|
||||
m_pEnd = NULL;
|
||||
}
|
||||
|
||||
virtual ~COMXOverlayText()
|
||||
{
|
||||
CElement* pTemp;
|
||||
while (m_pHead)
|
||||
{
|
||||
pTemp = m_pHead;
|
||||
m_pHead = m_pHead->pNext;
|
||||
delete pTemp;
|
||||
}
|
||||
}
|
||||
|
||||
void AddElement(COMXOverlayText::CElement* pElement)
|
||||
{
|
||||
pElement->pNext = NULL;
|
||||
|
||||
if (!m_pHead)
|
||||
{ // first element - set our head to this element, and update the end to the new element
|
||||
m_pHead = pElement;
|
||||
m_pEnd = pElement;
|
||||
}
|
||||
else
|
||||
{ // extra element - add to the end and update the end to the new element
|
||||
m_pEnd->pNext = pElement;
|
||||
m_pEnd = pElement;
|
||||
}
|
||||
}
|
||||
|
||||
CElement* m_pHead;
|
||||
CElement* m_pEnd;
|
||||
};
|
||||
|
||||
721
OMXPlayerAudio.cpp
Normal file
721
OMXPlayerAudio.cpp
Normal file
|
|
@ -0,0 +1,721 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#if (defined HAVE_CONFIG_H) && (!defined WIN32)
|
||||
#include "config.h"
|
||||
#elif defined(_WIN32)
|
||||
#include "system.h"
|
||||
#endif
|
||||
|
||||
#include "OMXPlayerAudio.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef STANDALONE
|
||||
#include "FileItem.h"
|
||||
#endif
|
||||
|
||||
#include "linux/XMemUtils.h"
|
||||
#ifndef STANDALONE
|
||||
#include "utils/BitstreamStats.h"
|
||||
#include "settings/GUISettings.h"
|
||||
#include "settings/Settings.h"
|
||||
#endif
|
||||
|
||||
#define MAX_DATA_SIZE 3 * 1024 * 1024
|
||||
|
||||
OMXPlayerAudio::OMXPlayerAudio()
|
||||
{
|
||||
m_open = false;
|
||||
m_stream_id = -1;
|
||||
m_pStream = NULL;
|
||||
m_av_clock = NULL;
|
||||
m_omx_reader = NULL;
|
||||
m_decoder = NULL;
|
||||
m_flush = false;
|
||||
m_cached_size = 0;
|
||||
m_pChannelMap = NULL;
|
||||
m_pAudioCodec = NULL;
|
||||
m_speed = DVD_PLAYSPEED_NORMAL;
|
||||
m_player_error = true;
|
||||
|
||||
pthread_cond_init(&m_packet_cond, NULL);
|
||||
pthread_cond_init(&m_audio_cond, NULL);
|
||||
pthread_mutex_init(&m_lock, NULL);
|
||||
pthread_mutex_init(&m_lock_decoder, NULL);
|
||||
}
|
||||
|
||||
OMXPlayerAudio::~OMXPlayerAudio()
|
||||
{
|
||||
Close();
|
||||
|
||||
pthread_cond_destroy(&m_audio_cond);
|
||||
pthread_cond_destroy(&m_packet_cond);
|
||||
pthread_mutex_destroy(&m_lock);
|
||||
pthread_mutex_destroy(&m_lock_decoder);
|
||||
}
|
||||
|
||||
void OMXPlayerAudio::Lock()
|
||||
{
|
||||
if(m_use_thread)
|
||||
pthread_mutex_lock(&m_lock);
|
||||
}
|
||||
|
||||
void OMXPlayerAudio::UnLock()
|
||||
{
|
||||
if(m_use_thread)
|
||||
pthread_mutex_unlock(&m_lock);
|
||||
}
|
||||
|
||||
void OMXPlayerAudio::LockDecoder()
|
||||
{
|
||||
if(m_use_thread)
|
||||
pthread_mutex_lock(&m_lock_decoder);
|
||||
}
|
||||
|
||||
void OMXPlayerAudio::UnLockDecoder()
|
||||
{
|
||||
if(m_use_thread)
|
||||
pthread_mutex_unlock(&m_lock_decoder);
|
||||
}
|
||||
|
||||
bool OMXPlayerAudio::Open(COMXStreamInfo &hints, OMXClock *av_clock, OMXReader *omx_reader, CStdString device,
|
||||
bool passthrough, bool hw_decode, bool use_thread)
|
||||
{
|
||||
if(ThreadHandle())
|
||||
Close();
|
||||
|
||||
if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllAvFormat.Load() || !av_clock)
|
||||
return false;
|
||||
|
||||
m_dllAvFormat.av_register_all();
|
||||
|
||||
m_hints = hints;
|
||||
m_av_clock = av_clock;
|
||||
m_omx_reader = omx_reader;
|
||||
m_device = device;
|
||||
m_passthrough = IAudioRenderer::ENCODED_NONE;
|
||||
m_hw_decode = false;
|
||||
m_use_passthrough = passthrough;
|
||||
m_use_hw_decode = hw_decode;
|
||||
m_iCurrentPts = DVD_NOPTS_VALUE;
|
||||
m_bAbort = false;
|
||||
m_bMpeg = m_omx_reader->IsMpegVideo();
|
||||
m_use_thread = use_thread;
|
||||
m_flush = false;
|
||||
m_cached_size = 0;
|
||||
m_pAudioCodec = NULL;
|
||||
m_pChannelMap = NULL;
|
||||
m_speed = DVD_PLAYSPEED_NORMAL;
|
||||
|
||||
m_error = 0;
|
||||
m_errorbuff = 0;
|
||||
m_errorcount = 0;
|
||||
m_integral = 0;
|
||||
m_skipdupcount = 0;
|
||||
m_prevskipped = false;
|
||||
m_syncclock = true;
|
||||
m_errortime = m_av_clock->CurrentHostCounter();
|
||||
|
||||
m_freq = m_av_clock->CurrentHostFrequency();
|
||||
|
||||
m_av_clock->SetMasterClock(false);
|
||||
|
||||
m_player_error = OpenAudioCodec();
|
||||
if(!m_player_error)
|
||||
{
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_player_error = OpenDecoder();
|
||||
if(!m_player_error)
|
||||
{
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(m_use_thread)
|
||||
Create();
|
||||
|
||||
m_open = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OMXPlayerAudio::Close()
|
||||
{
|
||||
m_bAbort = true;
|
||||
m_flush = true;
|
||||
|
||||
Flush();
|
||||
|
||||
if(ThreadHandle())
|
||||
{
|
||||
Lock();
|
||||
pthread_cond_broadcast(&m_packet_cond);
|
||||
UnLock();
|
||||
|
||||
StopThread();
|
||||
}
|
||||
|
||||
CloseDecoder();
|
||||
CloseAudioCodec();
|
||||
|
||||
m_open = false;
|
||||
m_stream_id = -1;
|
||||
m_iCurrentPts = DVD_NOPTS_VALUE;
|
||||
m_pStream = NULL;
|
||||
m_speed = DVD_PLAYSPEED_NORMAL;
|
||||
|
||||
m_dllAvUtil.Unload();
|
||||
m_dllAvCodec.Unload();
|
||||
m_dllAvFormat.Unload();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OMXPlayerAudio::HandleSyncError(double duration, double pts)
|
||||
{
|
||||
double clock = m_av_clock->GetClock();
|
||||
double error = pts - clock;
|
||||
int64_t now;
|
||||
|
||||
if( fabs(error) > DVD_MSEC_TO_TIME(100) || m_syncclock )
|
||||
{
|
||||
m_av_clock->Discontinuity(clock+error);
|
||||
/*
|
||||
if(m_speed == DVD_PLAYSPEED_NORMAL)
|
||||
printf("OMXPlayerAudio:: Discontinuity - was:%f, should be:%f, error:%f\n", clock, clock+error, error);
|
||||
*/
|
||||
|
||||
m_errorbuff = 0;
|
||||
m_errorcount = 0;
|
||||
m_skipdupcount = 0;
|
||||
m_error = 0;
|
||||
m_syncclock = false;
|
||||
m_errortime = m_av_clock->CurrentHostCounter();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_speed != DVD_PLAYSPEED_NORMAL)
|
||||
{
|
||||
m_errorbuff = 0;
|
||||
m_errorcount = 0;
|
||||
m_integral = 0;
|
||||
m_skipdupcount = 0;
|
||||
m_error = 0;
|
||||
m_errortime = m_av_clock->CurrentHostCounter();
|
||||
return;
|
||||
}
|
||||
|
||||
//check if measured error for 1 second
|
||||
now = m_av_clock->CurrentHostCounter();
|
||||
if ((now - m_errortime) >= m_freq)
|
||||
{
|
||||
m_errortime = now;
|
||||
m_error = m_errorbuff / m_errorcount;
|
||||
|
||||
m_errorbuff = 0;
|
||||
m_errorcount = 0;
|
||||
|
||||
/*
|
||||
if (m_synctype == SYNC_DISCON)
|
||||
{
|
||||
*/
|
||||
double limit, error;
|
||||
if (m_av_clock->GetRefreshRate(&limit) > 0)
|
||||
{
|
||||
//when the videoreferenceclock is running, the discontinuity limit is one vblank period
|
||||
limit *= DVD_TIME_BASE;
|
||||
|
||||
//make error a multiple of limit, rounded towards zero,
|
||||
//so it won't interfere with the sync methods in CXBMCRenderManager::WaitPresentTime
|
||||
if (m_error > 0.0)
|
||||
error = limit * floor(m_error / limit);
|
||||
else
|
||||
error = limit * ceil(m_error / limit);
|
||||
}
|
||||
else
|
||||
{
|
||||
limit = DVD_MSEC_TO_TIME(10);
|
||||
error = m_error;
|
||||
}
|
||||
|
||||
if (fabs(error) > limit - 0.001)
|
||||
{
|
||||
m_av_clock->Discontinuity(clock+error);
|
||||
/*
|
||||
if(m_speed == DVD_PLAYSPEED_NORMAL)
|
||||
CLog::Log(LOGDEBUG, "CDVDPlayerAudio:: Discontinuity - was:%f, should be:%f, error:%f", clock, clock+error, error);
|
||||
*/
|
||||
}
|
||||
}
|
||||
/*
|
||||
else if (m_synctype == SYNC_SKIPDUP && m_skipdupcount == 0 && fabs(m_error) > DVD_MSEC_TO_TIME(10))
|
||||
if (m_skipdupcount == 0 && fabs(m_error) > DVD_MSEC_TO_TIME(10))
|
||||
{
|
||||
//check how many packets to skip/duplicate
|
||||
m_skipdupcount = (int)(m_error / duration);
|
||||
//if less than one frame off, see if it's more than two thirds of a frame, so we can get better in sync
|
||||
if (m_skipdupcount == 0 && fabs(m_error) > duration / 3 * 2)
|
||||
m_skipdupcount = (int)(m_error / (duration / 3 * 2));
|
||||
|
||||
if (m_skipdupcount > 0)
|
||||
CLog::Log(LOGDEBUG, "OMXPlayerAudio:: Duplicating %i packet(s) of %.2f ms duration",
|
||||
m_skipdupcount, duration / DVD_TIME_BASE * 1000.0);
|
||||
else if (m_skipdupcount < 0)
|
||||
CLog::Log(LOGDEBUG, "OMXPlayerAudio:: Skipping %i packet(s) of %.2f ms duration ",
|
||||
m_skipdupcount * -1, duration / DVD_TIME_BASE * 1000.0);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
bool OMXPlayerAudio::Decode(OMXPacket *pkt)
|
||||
{
|
||||
if(!pkt)
|
||||
return false;
|
||||
|
||||
/* last decoder reinit went wrong */
|
||||
if(!m_decoder || !m_pAudioCodec)
|
||||
return true;
|
||||
|
||||
if(!m_omx_reader->IsActive(OMXSTREAM_AUDIO, pkt->stream_index))
|
||||
return true;
|
||||
|
||||
int channels = pkt->hints.channels;
|
||||
|
||||
/* 6 channel have to be mapped to 8 for PCM */
|
||||
if(!m_passthrough && !m_hw_decode)
|
||||
{
|
||||
if(channels == 6)
|
||||
channels = 8;
|
||||
}
|
||||
|
||||
unsigned int old_bitrate = m_hints.bitrate;
|
||||
unsigned int new_bitrate = pkt->hints.bitrate;
|
||||
|
||||
/* only check bitrate changes on CODEC_ID_DTS, CODEC_ID_AC3, CODEC_ID_EAC3 */
|
||||
if(m_hints.codec != CODEC_ID_DTS && m_hints.codec != CODEC_ID_AC3 && m_hints.codec != CODEC_ID_EAC3)
|
||||
{
|
||||
new_bitrate = old_bitrate = 0;
|
||||
}
|
||||
|
||||
/* audio codec changed. reinit device and decoder */
|
||||
if(m_hints.codec != pkt->hints.codec ||
|
||||
m_hints.channels != channels ||
|
||||
m_hints.samplerate != pkt->hints.samplerate ||
|
||||
old_bitrate != new_bitrate ||
|
||||
m_hints.bitspersample != pkt->hints.bitspersample)
|
||||
{
|
||||
printf("C : %d %d %d %d %d\n", m_hints.codec, m_hints.channels, m_hints.samplerate, m_hints.bitrate, m_hints.bitspersample);
|
||||
printf("N : %d %d %d %d %d\n", pkt->hints.codec, channels, pkt->hints.samplerate, pkt->hints.bitrate, pkt->hints.bitspersample);
|
||||
|
||||
m_av_clock->OMXPause();
|
||||
|
||||
CloseDecoder();
|
||||
CloseAudioCodec();
|
||||
|
||||
m_hints = pkt->hints;
|
||||
|
||||
m_player_error = OpenAudioCodec();
|
||||
if(!m_player_error)
|
||||
return false;
|
||||
|
||||
m_player_error = OpenDecoder();
|
||||
if(!m_player_error)
|
||||
return false;
|
||||
|
||||
m_av_clock->OMXStateExecute();
|
||||
m_av_clock->OMXReset();
|
||||
m_av_clock->OMXResume();
|
||||
|
||||
}
|
||||
|
||||
if(!((unsigned long)m_decoder->GetSpace() > pkt->size))
|
||||
OMXClock::OMXSleep(10);
|
||||
|
||||
if((unsigned long)m_decoder->GetSpace() > pkt->size)
|
||||
{
|
||||
if(pkt->dts != DVD_NOPTS_VALUE)
|
||||
m_iCurrentPts = pkt->dts;
|
||||
|
||||
m_av_clock->SetPTS(m_iCurrentPts);
|
||||
|
||||
const uint8_t *data_dec = pkt->data;
|
||||
int data_len = pkt->size;
|
||||
|
||||
if(!m_passthrough && !m_hw_decode)
|
||||
{
|
||||
while(data_len > 0)
|
||||
{
|
||||
int len = m_pAudioCodec->Decode((BYTE *)data_dec, data_len);
|
||||
if( (len < 0) || (len > data_len) )
|
||||
{
|
||||
m_pAudioCodec->Reset();
|
||||
break;
|
||||
}
|
||||
|
||||
data_dec+= len;
|
||||
data_len -= len;
|
||||
|
||||
uint8_t *decoded;
|
||||
int decoded_size = m_pAudioCodec->GetData(&decoded);
|
||||
|
||||
if(decoded_size <=0)
|
||||
continue;
|
||||
|
||||
int ret = 0;
|
||||
|
||||
if(m_bMpeg)
|
||||
ret = m_decoder->AddPackets(decoded, decoded_size, DVD_NOPTS_VALUE, DVD_NOPTS_VALUE);
|
||||
else
|
||||
ret = m_decoder->AddPackets(decoded, decoded_size, m_iCurrentPts, m_iCurrentPts);
|
||||
|
||||
if(ret != decoded_size)
|
||||
{
|
||||
printf("error ret %d decoded_size %d\n", ret, decoded_size);
|
||||
}
|
||||
|
||||
int n = (m_hints.channels * m_hints.bitspersample * m_hints.samplerate)>>3;
|
||||
if (n > 0 && m_iCurrentPts != DVD_NOPTS_VALUE)
|
||||
m_iCurrentPts += ((double)decoded_size * DVD_TIME_BASE) / n;
|
||||
|
||||
HandleSyncError((((double)decoded_size * DVD_TIME_BASE) / n), m_iCurrentPts);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_bMpeg)
|
||||
m_decoder->AddPackets(pkt->data, pkt->size, DVD_NOPTS_VALUE, DVD_NOPTS_VALUE);
|
||||
else
|
||||
m_decoder->AddPackets(pkt->data, pkt->size, m_iCurrentPts, m_iCurrentPts);
|
||||
|
||||
HandleSyncError(0, m_iCurrentPts);
|
||||
}
|
||||
|
||||
m_av_clock->SetAudioClock(m_iCurrentPts);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void OMXPlayerAudio::Process()
|
||||
{
|
||||
OMXPacket *omx_pkt = NULL;
|
||||
|
||||
while(!m_bStop && !m_bAbort)
|
||||
{
|
||||
Lock();
|
||||
if(m_packets.empty())
|
||||
pthread_cond_wait(&m_packet_cond, &m_lock);
|
||||
UnLock();
|
||||
|
||||
if(m_bAbort)
|
||||
break;
|
||||
|
||||
Lock();
|
||||
if(m_flush && omx_pkt)
|
||||
{
|
||||
OMXReader::FreePacket(omx_pkt);
|
||||
omx_pkt = NULL;
|
||||
m_flush = false;
|
||||
}
|
||||
else if(!omx_pkt && !m_packets.empty())
|
||||
{
|
||||
omx_pkt = m_packets.front();
|
||||
m_cached_size -= omx_pkt->size;
|
||||
m_packets.pop_front();
|
||||
}
|
||||
UnLock();
|
||||
|
||||
LockDecoder();
|
||||
if(m_flush && omx_pkt)
|
||||
{
|
||||
OMXReader::FreePacket(omx_pkt);
|
||||
omx_pkt = NULL;
|
||||
m_flush = false;
|
||||
}
|
||||
else if(omx_pkt && Decode(omx_pkt))
|
||||
{
|
||||
OMXReader::FreePacket(omx_pkt);
|
||||
omx_pkt = NULL;
|
||||
}
|
||||
UnLockDecoder();
|
||||
}
|
||||
|
||||
if(omx_pkt)
|
||||
OMXReader::FreePacket(omx_pkt);
|
||||
}
|
||||
|
||||
void OMXPlayerAudio::Flush()
|
||||
{
|
||||
Lock();
|
||||
LockDecoder();
|
||||
m_flush = true;
|
||||
while (!m_packets.empty())
|
||||
{
|
||||
OMXPacket *pkt = m_packets.front();
|
||||
m_packets.pop_front();
|
||||
OMXReader::FreePacket(pkt);
|
||||
}
|
||||
m_iCurrentPts = DVD_NOPTS_VALUE;
|
||||
m_cached_size = 0;
|
||||
if(m_decoder)
|
||||
m_decoder->Flush();
|
||||
m_syncclock = true;
|
||||
UnLockDecoder();
|
||||
UnLock();
|
||||
}
|
||||
|
||||
bool OMXPlayerAudio::AddPacket(OMXPacket *pkt)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if(!pkt)
|
||||
return ret;
|
||||
|
||||
if(m_bStop || m_bAbort)
|
||||
return ret;
|
||||
|
||||
if((m_cached_size + pkt->size) < MAX_DATA_SIZE)
|
||||
{
|
||||
Lock();
|
||||
m_cached_size += pkt->size;
|
||||
m_packets.push_back(pkt);
|
||||
UnLock();
|
||||
ret = true;
|
||||
pthread_cond_broadcast(&m_packet_cond);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool OMXPlayerAudio::OpenAudioCodec()
|
||||
{
|
||||
m_pAudioCodec = new COMXAudioCodecOMX();
|
||||
|
||||
if(!m_pAudioCodec->Open(m_hints))
|
||||
{
|
||||
delete m_pAudioCodec; m_pAudioCodec = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pChannelMap = m_pAudioCodec->GetChannelMap();
|
||||
return true;
|
||||
}
|
||||
|
||||
void OMXPlayerAudio::CloseAudioCodec()
|
||||
{
|
||||
if(m_pAudioCodec)
|
||||
delete m_pAudioCodec;
|
||||
m_pAudioCodec = NULL;
|
||||
}
|
||||
|
||||
IAudioRenderer::EEncoded OMXPlayerAudio::IsPassthrough(COMXStreamInfo hints)
|
||||
{
|
||||
#ifndef STANDALONE
|
||||
int m_outputmode = 0;
|
||||
bool bitstream = false;
|
||||
IAudioRenderer::EEncoded passthrough = IAudioRenderer::ENCODED_NONE;
|
||||
|
||||
m_outputmode = g_guiSettings.GetInt("audiooutput.mode");
|
||||
|
||||
switch(m_outputmode)
|
||||
{
|
||||
case 0:
|
||||
passthrough = IAudioRenderer::ENCODED_NONE;
|
||||
break;
|
||||
case 1:
|
||||
bitstream = true;
|
||||
break;
|
||||
case 2:
|
||||
bitstream = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if(bitstream)
|
||||
{
|
||||
if(hints.codec == CODEC_ID_AC3 && g_guiSettings.GetBool("audiooutput.ac3passthrough"))
|
||||
{
|
||||
passthrough = IAudioRenderer::ENCODED_IEC61937_AC3;
|
||||
}
|
||||
if(hints.codec == CODEC_ID_DTS && g_guiSettings.GetBool("audiooutput.dtspassthrough"))
|
||||
{
|
||||
passthrough = IAudioRenderer::ENCODED_IEC61937_DTS;
|
||||
}
|
||||
}
|
||||
|
||||
return passthrough;
|
||||
#else
|
||||
if(m_device == "omx:local")
|
||||
return IAudioRenderer::ENCODED_NONE;
|
||||
|
||||
IAudioRenderer::EEncoded passthrough = IAudioRenderer::ENCODED_NONE;
|
||||
|
||||
if(hints.codec == CODEC_ID_AC3)
|
||||
{
|
||||
passthrough = IAudioRenderer::ENCODED_IEC61937_AC3;
|
||||
}
|
||||
if(hints.codec == CODEC_ID_EAC3)
|
||||
{
|
||||
passthrough = IAudioRenderer::ENCODED_IEC61937_EAC3;
|
||||
}
|
||||
if(hints.codec == CODEC_ID_DTS)
|
||||
{
|
||||
passthrough = IAudioRenderer::ENCODED_IEC61937_DTS;
|
||||
}
|
||||
|
||||
return passthrough;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool OMXPlayerAudio::OpenDecoder()
|
||||
{
|
||||
bool bAudioRenderOpen = false;
|
||||
|
||||
m_decoder = new COMXAudio();
|
||||
m_decoder->SetClock(m_av_clock);
|
||||
|
||||
if(m_use_passthrough)
|
||||
m_passthrough = IsPassthrough(m_hints);
|
||||
|
||||
if(!m_passthrough && m_use_hw_decode)
|
||||
m_hw_decode = COMXAudio::HWDecode(m_hints.codec);
|
||||
|
||||
if(m_passthrough || m_use_hw_decode)
|
||||
{
|
||||
if(m_passthrough)
|
||||
m_hw_decode = false;
|
||||
bAudioRenderOpen = m_decoder->Initialize(NULL, m_device.substr(4), m_pChannelMap,
|
||||
m_hints, m_av_clock, m_passthrough, m_hw_decode);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* omx needs 6 channels packed into 8 for PCM */
|
||||
if(m_hints.channels == 6)
|
||||
m_hints.channels = 8;
|
||||
|
||||
bAudioRenderOpen = m_decoder->Initialize(NULL, m_device.substr(4), m_hints.channels, m_pChannelMap,
|
||||
m_hints.samplerate, m_hints.bitspersample,
|
||||
false, false, m_passthrough);
|
||||
}
|
||||
|
||||
m_codec_name = m_omx_reader->GetCodecName(OMXSTREAM_AUDIO);
|
||||
|
||||
if(!bAudioRenderOpen)
|
||||
{
|
||||
delete m_decoder;
|
||||
m_decoder = NULL;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_passthrough)
|
||||
{
|
||||
printf("Audio codec %s channels %d samplerate %d bitspersample %d\n",
|
||||
m_codec_name.c_str(), 2, m_hints.samplerate, m_hints.bitspersample);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Audio codec %s channels %d samplerate %d bitspersample %d\n",
|
||||
m_codec_name.c_str(), m_hints.channels, m_hints.samplerate, m_hints.bitspersample);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OMXPlayerAudio::CloseDecoder()
|
||||
{
|
||||
if(m_decoder)
|
||||
delete m_decoder;
|
||||
m_decoder = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
double OMXPlayerAudio::GetDelay()
|
||||
{
|
||||
if(m_decoder)
|
||||
return m_decoder->GetDelay();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
double OMXPlayerAudio::GetCacheTime()
|
||||
{
|
||||
if(m_decoder)
|
||||
return m_decoder->GetCacheTime();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OMXPlayerAudio::WaitCompletion()
|
||||
{
|
||||
if(!m_decoder)
|
||||
return;
|
||||
|
||||
while(true)
|
||||
{
|
||||
Lock();
|
||||
if(m_packets.empty())
|
||||
{
|
||||
UnLock();
|
||||
break;
|
||||
}
|
||||
UnLock();
|
||||
OMXClock::OMXSleep(50);
|
||||
}
|
||||
|
||||
m_decoder->WaitCompletion();
|
||||
}
|
||||
|
||||
void OMXPlayerAudio::RegisterAudioCallback(IAudioCallback *pCallback)
|
||||
{
|
||||
if(m_decoder) m_decoder->RegisterAudioCallback(pCallback);
|
||||
|
||||
}
|
||||
void OMXPlayerAudio::UnRegisterAudioCallback()
|
||||
{
|
||||
if(m_decoder) m_decoder->UnRegisterAudioCallback();
|
||||
}
|
||||
|
||||
void OMXPlayerAudio::DoAudioWork()
|
||||
{
|
||||
if(m_decoder) m_decoder->DoAudioWork();
|
||||
}
|
||||
|
||||
void OMXPlayerAudio::SetCurrentVolume(long nVolume)
|
||||
{
|
||||
if(m_decoder) m_decoder->SetCurrentVolume(nVolume);
|
||||
}
|
||||
|
||||
void OMXPlayerAudio::SetSpeed(int speed)
|
||||
{
|
||||
m_speed = speed;
|
||||
}
|
||||
|
||||
135
OMXPlayerAudio.h
Normal file
135
OMXPlayerAudio.h
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _OMX_PLAYERAUDIO_H_
|
||||
#define _OMX_PLAYERAUDIO_H_
|
||||
|
||||
#include "utils/StdString.h"
|
||||
#include "DllAvUtil.h"
|
||||
#include "DllAvFormat.h"
|
||||
#include "DllAvFilter.h"
|
||||
#include "DllAvCodec.h"
|
||||
#include "DllAvCore.h"
|
||||
|
||||
#include "utils/PCMRemap.h"
|
||||
|
||||
#include "OMXReader.h"
|
||||
#include "OMXClock.h"
|
||||
#include "OMXStreamInfo.h"
|
||||
#include "OMXAudio.h"
|
||||
#include "OMXAudioCodecOMX.h"
|
||||
#ifdef STANDALONE
|
||||
#include "OMXThread.h"
|
||||
#else
|
||||
#include "threads/Thread.h"
|
||||
#endif
|
||||
|
||||
#include <deque>
|
||||
#include <sys/types.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#ifdef STANDALONE
|
||||
class OMXPlayerAudio : public OMXThread
|
||||
#else
|
||||
class OMXPlayerAudio : public CThread
|
||||
#endif
|
||||
{
|
||||
protected:
|
||||
AVStream *m_pStream;
|
||||
int m_stream_id;
|
||||
std::deque<OMXPacket *> m_packets;
|
||||
DllAvUtil m_dllAvUtil;
|
||||
DllAvCodec m_dllAvCodec;
|
||||
DllAvFormat m_dllAvFormat;
|
||||
bool m_open;
|
||||
COMXStreamInfo m_hints;
|
||||
double m_iCurrentPts;
|
||||
pthread_cond_t m_packet_cond;
|
||||
pthread_cond_t m_audio_cond;
|
||||
pthread_mutex_t m_lock;
|
||||
pthread_mutex_t m_lock_decoder;
|
||||
OMXClock *m_av_clock;
|
||||
OMXReader *m_omx_reader;
|
||||
COMXAudio *m_decoder;
|
||||
CStdString m_codec_name;
|
||||
CStdString m_device;
|
||||
bool m_use_passthrough;
|
||||
bool m_use_hw_decode;
|
||||
IAudioRenderer::EEncoded m_passthrough;
|
||||
bool m_hw_decode;
|
||||
bool m_bMpeg;
|
||||
bool m_bAbort;
|
||||
bool m_use_thread;
|
||||
bool m_flush;
|
||||
enum PCMChannels *m_pChannelMap;
|
||||
unsigned int m_cached_size;
|
||||
COMXAudioCodecOMX *m_pAudioCodec;
|
||||
int m_speed;
|
||||
double m_error; //last average error
|
||||
|
||||
int64_t m_errortime; //timestamp of last time we measured
|
||||
int64_t m_freq;
|
||||
|
||||
void HandleSyncError(double duration, double pts);
|
||||
double m_errorbuff; //place to store average errors
|
||||
int m_errorcount;//number of errors stored
|
||||
bool m_syncclock;
|
||||
|
||||
bool m_player_error;
|
||||
|
||||
double m_integral; //integral correction for resampler
|
||||
int m_skipdupcount; //counter for skip/duplicate synctype
|
||||
bool m_prevskipped;
|
||||
|
||||
void Lock();
|
||||
void UnLock();
|
||||
void LockDecoder();
|
||||
void UnLockDecoder();
|
||||
private:
|
||||
public:
|
||||
OMXPlayerAudio();
|
||||
~OMXPlayerAudio();
|
||||
bool Open(COMXStreamInfo &hints, OMXClock *av_clock, OMXReader *omx_reader, CStdString device,
|
||||
bool passthrough, bool hw_decode, bool use_thread);
|
||||
bool Close();
|
||||
bool Decode(OMXPacket *pkt);
|
||||
void Process();
|
||||
void Flush();
|
||||
bool AddPacket(OMXPacket *pkt);
|
||||
bool OpenAudioCodec();
|
||||
void CloseAudioCodec();
|
||||
IAudioRenderer::EEncoded IsPassthrough(COMXStreamInfo hints);
|
||||
bool OpenDecoder();
|
||||
bool CloseDecoder();
|
||||
double GetDelay();
|
||||
double GetCacheTime();
|
||||
double GetCurrentPTS() { return m_iCurrentPts; };
|
||||
void WaitCompletion();
|
||||
unsigned int GetCached() { return m_cached_size; };
|
||||
void RegisterAudioCallback(IAudioCallback* pCallback);
|
||||
void UnRegisterAudioCallback();
|
||||
void DoAudioWork();
|
||||
void SetCurrentVolume(long nVolume);
|
||||
void SetSpeed(int iSpeed);
|
||||
bool Error() { return !m_player_error; };
|
||||
};
|
||||
#endif
|
||||
630
OMXPlayerVideo.cpp
Normal file
630
OMXPlayerVideo.cpp
Normal file
|
|
@ -0,0 +1,630 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#if (defined HAVE_CONFIG_H) && (!defined WIN32)
|
||||
#include "config.h"
|
||||
#elif defined(_WIN32)
|
||||
#include "system.h"
|
||||
#endif
|
||||
|
||||
#include "OMXPlayerVideo.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifndef STANDALONE
|
||||
#include "FileItem.h"
|
||||
#endif
|
||||
|
||||
#include "linux/XMemUtils.h"
|
||||
#ifndef STANDALONE
|
||||
#include "utils/BitstreamStats.h"
|
||||
#endif
|
||||
|
||||
#define MAX_DATA_SIZE 10 * 1024 * 1024
|
||||
|
||||
OMXPlayerVideo::OMXPlayerVideo()
|
||||
{
|
||||
m_open = false;
|
||||
m_stream_id = -1;
|
||||
m_pStream = NULL;
|
||||
m_av_clock = NULL;
|
||||
m_decoder = NULL;
|
||||
m_fps = 25.0f;
|
||||
m_flush = false;
|
||||
m_cached_size = 0;
|
||||
m_hdmi_clock_sync = false;
|
||||
m_iVideoDelay = 0;
|
||||
m_pts = 0;
|
||||
m_syncclock = true;
|
||||
m_speed = DVD_PLAYSPEED_NORMAL;
|
||||
m_iSubtitleDelay = 0;
|
||||
m_pSubtitleCodec = NULL;
|
||||
|
||||
pthread_cond_init(&m_packet_cond, NULL);
|
||||
pthread_cond_init(&m_picture_cond, NULL);
|
||||
pthread_mutex_init(&m_lock, NULL);
|
||||
pthread_mutex_init(&m_lock_decoder, NULL);
|
||||
pthread_mutex_init(&m_lock_subtitle, NULL);
|
||||
}
|
||||
|
||||
OMXPlayerVideo::~OMXPlayerVideo()
|
||||
{
|
||||
Close();
|
||||
|
||||
pthread_cond_destroy(&m_packet_cond);
|
||||
pthread_cond_destroy(&m_picture_cond);
|
||||
pthread_mutex_destroy(&m_lock);
|
||||
pthread_mutex_destroy(&m_lock_decoder);
|
||||
pthread_mutex_destroy(&m_lock_subtitle);
|
||||
}
|
||||
|
||||
void OMXPlayerVideo::Lock()
|
||||
{
|
||||
if(m_use_thread)
|
||||
pthread_mutex_lock(&m_lock);
|
||||
}
|
||||
|
||||
void OMXPlayerVideo::UnLock()
|
||||
{
|
||||
if(m_use_thread)
|
||||
pthread_mutex_unlock(&m_lock);
|
||||
}
|
||||
|
||||
void OMXPlayerVideo::LockDecoder()
|
||||
{
|
||||
if(m_use_thread)
|
||||
pthread_mutex_lock(&m_lock_decoder);
|
||||
}
|
||||
|
||||
void OMXPlayerVideo::UnLockDecoder()
|
||||
{
|
||||
if(m_use_thread)
|
||||
pthread_mutex_unlock(&m_lock_decoder);
|
||||
}
|
||||
|
||||
void OMXPlayerVideo::LockSubtitles()
|
||||
{
|
||||
if(m_use_thread)
|
||||
pthread_mutex_lock(&m_lock_subtitle);
|
||||
}
|
||||
|
||||
void OMXPlayerVideo::UnLockSubtitles()
|
||||
{
|
||||
if(m_use_thread)
|
||||
pthread_mutex_unlock(&m_lock_subtitle);
|
||||
}
|
||||
|
||||
bool OMXPlayerVideo::Open(COMXStreamInfo &hints, OMXClock *av_clock, bool deinterlace, bool mpeg, int has_audio, bool hdmi_clock_sync, bool use_thread)
|
||||
{
|
||||
if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllAvFormat.Load() || !av_clock)
|
||||
return false;
|
||||
|
||||
if(ThreadHandle())
|
||||
Close();
|
||||
|
||||
m_dllAvFormat.av_register_all();
|
||||
|
||||
m_hints = hints;
|
||||
m_av_clock = av_clock;
|
||||
m_fps = 25.0f;
|
||||
m_frametime = 0;
|
||||
m_Deinterlace = deinterlace;
|
||||
m_bMpeg = mpeg;
|
||||
m_iCurrentPts = DVD_NOPTS_VALUE;
|
||||
m_has_audio = has_audio;
|
||||
m_bAbort = false;
|
||||
m_use_thread = use_thread;
|
||||
m_flush = false;
|
||||
m_cached_size = 0;
|
||||
m_iVideoDelay = 0;
|
||||
m_hdmi_clock_sync = hdmi_clock_sync;
|
||||
m_pts = 0;
|
||||
m_syncclock = true;
|
||||
m_speed = DVD_PLAYSPEED_NORMAL;
|
||||
m_iSubtitleDelay = 0;
|
||||
m_pSubtitleCodec = NULL;
|
||||
|
||||
m_FlipTimeStamp = m_av_clock->GetAbsoluteClock();
|
||||
|
||||
if(!OpenDecoder())
|
||||
{
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(m_use_thread)
|
||||
Create();
|
||||
|
||||
m_open = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OMXPlayerVideo::Close()
|
||||
{
|
||||
m_bAbort = true;
|
||||
m_flush = true;
|
||||
|
||||
Flush();
|
||||
|
||||
if(ThreadHandle())
|
||||
{
|
||||
Lock();
|
||||
pthread_cond_broadcast(&m_packet_cond);
|
||||
UnLock();
|
||||
|
||||
StopThread();
|
||||
}
|
||||
|
||||
CloseDecoder();
|
||||
|
||||
m_dllAvUtil.Unload();
|
||||
m_dllAvCodec.Unload();
|
||||
m_dllAvFormat.Unload();
|
||||
|
||||
m_open = false;
|
||||
m_stream_id = -1;
|
||||
m_iCurrentPts = DVD_NOPTS_VALUE;
|
||||
m_pStream = NULL;
|
||||
m_pts = 0;
|
||||
m_syncclock = true;
|
||||
m_speed = DVD_PLAYSPEED_NORMAL;
|
||||
m_pSubtitleCodec = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OMXPlayerVideo::Output(double pts)
|
||||
{
|
||||
if(m_syncclock)
|
||||
{
|
||||
double delay = m_FlipTimeStamp - m_av_clock->GetAbsoluteClock();
|
||||
if( delay > m_frametime ) delay = m_frametime;
|
||||
else if( delay < 0 ) delay = 0;
|
||||
|
||||
//printf("OMXPlayerVideo - GENERAL_RESYNC(%f, 1) delay %f\n", pts, m_FlipTimeStamp);
|
||||
m_av_clock->Discontinuity(pts - delay);
|
||||
m_syncclock = false;
|
||||
}
|
||||
|
||||
double iSleepTime, iClockSleep, iFrameSleep, iPlayingClock, iCurrentClock, iFrameDuration;
|
||||
iPlayingClock = m_av_clock->GetClock(iCurrentClock, false); // snapshot current clock
|
||||
iClockSleep = pts - iPlayingClock; //sleep calculated by pts to clock comparison
|
||||
iFrameSleep = m_FlipTimeStamp - iCurrentClock; // sleep calculated by duration of frame
|
||||
iFrameDuration = m_frametime;
|
||||
|
||||
// correct sleep times based on speed
|
||||
if(m_speed)
|
||||
{
|
||||
iClockSleep = iClockSleep * DVD_PLAYSPEED_NORMAL / m_speed;
|
||||
iFrameSleep = iFrameSleep * DVD_PLAYSPEED_NORMAL / abs(m_speed);
|
||||
iFrameDuration = iFrameDuration * DVD_PLAYSPEED_NORMAL / abs(m_speed);
|
||||
}
|
||||
else
|
||||
{
|
||||
iClockSleep = 0;
|
||||
iFrameSleep = 0;
|
||||
}
|
||||
// dropping to a very low framerate is not correct (it should not happen at all)
|
||||
iClockSleep = min(iClockSleep, DVD_MSEC_TO_TIME(500));
|
||||
iFrameSleep = min(iFrameSleep, DVD_MSEC_TO_TIME(500));
|
||||
|
||||
bool m_stalled = false;
|
||||
int m_autosync = 1;
|
||||
if( m_stalled )
|
||||
iSleepTime = iFrameSleep;
|
||||
else
|
||||
iSleepTime = iFrameSleep + (iClockSleep - iFrameSleep) / m_autosync;
|
||||
|
||||
// present the current pts of this frame to user, and include the actual
|
||||
// presentation delay, to allow him to adjust for it
|
||||
if( m_stalled )
|
||||
m_iCurrentPts = DVD_NOPTS_VALUE;
|
||||
else
|
||||
m_iCurrentPts = pts - max(0.0, iSleepTime);
|
||||
|
||||
// timestamp when we think next picture should be displayed based on current duration
|
||||
m_FlipTimeStamp = iCurrentClock;
|
||||
m_FlipTimeStamp += max(0.0, iSleepTime);
|
||||
m_FlipTimeStamp += iFrameDuration;
|
||||
|
||||
while(m_av_clock->GetAbsoluteClock(false) < (iCurrentClock + iSleepTime + DVD_MSEC_TO_TIME(500)) )
|
||||
{
|
||||
OMXClock::OMXSleep(10);
|
||||
}
|
||||
|
||||
/*
|
||||
printf("iPlayingClock %f iCurrentClock %f iClockSleep %f iFrameSleep %f iFrameDuration %f WaitAbsolut %f m_FlipTimeStamp %f pts %f\n",
|
||||
iPlayingClock / DVD_TIME_BASE, iCurrentClock / DVD_TIME_BASE,
|
||||
iClockSleep / DVD_TIME_BASE, iFrameSleep / DVD_TIME_BASE,
|
||||
iFrameDuration / DVD_TIME_BASE, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, m_FlipTimeStamp / DVD_TIME_BASE,
|
||||
pts / DVD_TIME_BASE);
|
||||
*/
|
||||
|
||||
//g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, -1, mDisplayField);
|
||||
|
||||
m_av_clock->WaitAbsoluteClock((iCurrentClock + iSleepTime));
|
||||
|
||||
// guess next frame pts. iDuration is always valid
|
||||
if (m_speed != 0)
|
||||
m_pts += m_frametime * m_speed / abs(m_speed);
|
||||
}
|
||||
|
||||
bool OMXPlayerVideo::Decode(OMXPacket *pkt)
|
||||
{
|
||||
if(!pkt)
|
||||
return false;
|
||||
|
||||
bool ret = false;
|
||||
|
||||
if(!((unsigned long)m_decoder->GetFreeSpace() > pkt->size))
|
||||
OMXClock::OMXSleep(10);
|
||||
|
||||
if (pkt->dts == DVD_NOPTS_VALUE && pkt->pts == DVD_NOPTS_VALUE)
|
||||
pkt->pts = m_pts;
|
||||
else if (pkt->pts == DVD_NOPTS_VALUE)
|
||||
pkt->pts = pkt->dts;
|
||||
|
||||
if(pkt->pts != DVD_NOPTS_VALUE)
|
||||
{
|
||||
m_pts = pkt->pts;
|
||||
m_pts += m_iVideoDelay;
|
||||
}
|
||||
|
||||
if(pkt->hints.codec == CODEC_ID_TEXT ||
|
||||
pkt->hints.codec == CODEC_ID_SSA )
|
||||
{
|
||||
if(!m_pSubtitleCodec)
|
||||
{
|
||||
m_pSubtitleCodec = new COMXOverlayCodecText();
|
||||
m_pSubtitleCodec->Open( pkt->hints );
|
||||
}
|
||||
int result = m_pSubtitleCodec->Decode(pkt->data, pkt->size, pkt->pts, pkt->duration);
|
||||
COMXOverlay* overlay;
|
||||
|
||||
CStdString strSubtitle = "";
|
||||
|
||||
double pts = pkt->dts != DVD_NOPTS_VALUE ? pkt->dts : pkt->pts;
|
||||
double duration = pkt->duration;
|
||||
|
||||
if(result == OC_OVERLAY)
|
||||
{
|
||||
|
||||
while((overlay = m_pSubtitleCodec->GetOverlay()) != NULL)
|
||||
{
|
||||
if(overlay->iPTSStopTime > overlay->iPTSStartTime)
|
||||
duration = overlay->iPTSStopTime - overlay->iPTSStartTime;
|
||||
else if(pkt->duration != DVD_NOPTS_VALUE)
|
||||
duration = pkt->duration;
|
||||
else
|
||||
duration = 0.0;
|
||||
|
||||
if (pkt->pts != DVD_NOPTS_VALUE)
|
||||
pts = pkt->pts;
|
||||
else if(pkt->dts != DVD_NOPTS_VALUE)
|
||||
pts = pkt->dts;
|
||||
else
|
||||
pts = overlay->iPTSStartTime;
|
||||
|
||||
pts -= m_iSubtitleDelay;
|
||||
|
||||
overlay->iPTSStartTime = pts;
|
||||
if(duration)
|
||||
overlay->iPTSStopTime = pts + duration;
|
||||
else
|
||||
{
|
||||
overlay->iPTSStopTime = 0;
|
||||
overlay->replace = true;
|
||||
}
|
||||
|
||||
COMXOverlayText::CElement* e = ((COMXOverlayText*)overlay)->m_pHead;
|
||||
while (e)
|
||||
{
|
||||
if (e->IsElementType(COMXOverlayText::ELEMENT_TYPE_TEXT))
|
||||
{
|
||||
COMXOverlayText::CElementText* t = (COMXOverlayText::CElementText*)e;
|
||||
strSubtitle += t->m_text;
|
||||
strSubtitle += "\n";
|
||||
}
|
||||
e = e->pNext;
|
||||
}
|
||||
|
||||
m_overlays.push_back(overlay);
|
||||
|
||||
if(strSubtitle.length())
|
||||
m_decoder->DecodeText((uint8_t *)strSubtitle.c_str(), strSubtitle.length(), overlay->iPTSStartTime, overlay->iPTSStartTime);
|
||||
}
|
||||
}
|
||||
|
||||
ret = true;
|
||||
}
|
||||
else if((unsigned long)m_decoder->GetFreeSpace() > pkt->size)
|
||||
{
|
||||
if(m_bMpeg)
|
||||
m_decoder->Decode(pkt->data, pkt->size, DVD_NOPTS_VALUE, DVD_NOPTS_VALUE);
|
||||
else
|
||||
m_decoder->Decode(pkt->data, pkt->size, m_pts, m_pts);
|
||||
|
||||
m_av_clock->SetVideoClock(m_pts);
|
||||
|
||||
Output(m_pts);
|
||||
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void OMXPlayerVideo::Process()
|
||||
{
|
||||
OMXPacket *omx_pkt = NULL;
|
||||
|
||||
m_pts = 0;
|
||||
|
||||
while(!m_bStop && !m_bAbort)
|
||||
{
|
||||
Lock();
|
||||
if(m_packets.empty())
|
||||
pthread_cond_wait(&m_packet_cond, &m_lock);
|
||||
UnLock();
|
||||
|
||||
if(m_bAbort)
|
||||
break;
|
||||
|
||||
Lock();
|
||||
if(m_flush && omx_pkt)
|
||||
{
|
||||
OMXReader::FreePacket(omx_pkt);
|
||||
omx_pkt = NULL;
|
||||
m_flush = false;
|
||||
}
|
||||
else if(!omx_pkt && !m_packets.empty())
|
||||
{
|
||||
omx_pkt = m_packets.front();
|
||||
m_cached_size -= omx_pkt->size;
|
||||
m_packets.pop_front();
|
||||
}
|
||||
UnLock();
|
||||
|
||||
LockDecoder();
|
||||
if(m_flush && omx_pkt)
|
||||
{
|
||||
OMXReader::FreePacket(omx_pkt);
|
||||
omx_pkt = NULL;
|
||||
m_flush = false;
|
||||
}
|
||||
else if(omx_pkt && Decode(omx_pkt))
|
||||
{
|
||||
OMXReader::FreePacket(omx_pkt);
|
||||
omx_pkt = NULL;
|
||||
}
|
||||
UnLockDecoder();
|
||||
|
||||
OMXPacket *subtitle_pkt = m_decoder->GetText();
|
||||
|
||||
if(subtitle_pkt)
|
||||
{
|
||||
LockSubtitles();
|
||||
subtitle_pkt->pts = m_av_clock->GetClock();
|
||||
m_subtitle_packets.push_back(subtitle_pkt);
|
||||
UnLockSubtitles();
|
||||
}
|
||||
}
|
||||
|
||||
if(omx_pkt)
|
||||
OMXReader::FreePacket(omx_pkt);
|
||||
}
|
||||
|
||||
void OMXPlayerVideo::FlushSubtitles()
|
||||
{
|
||||
LockDecoder();
|
||||
LockSubtitles();
|
||||
while (!m_subtitle_packets.empty())
|
||||
{
|
||||
OMXPacket *pkt = m_subtitle_packets.front();
|
||||
m_subtitle_packets.pop_front();
|
||||
OMXReader::FreePacket(pkt);
|
||||
}
|
||||
while (!m_overlays.empty())
|
||||
{
|
||||
COMXOverlay *overlay = m_overlays.front();
|
||||
m_overlays.pop_front();
|
||||
delete overlay;
|
||||
}
|
||||
if(m_pSubtitleCodec)
|
||||
delete m_pSubtitleCodec;
|
||||
m_pSubtitleCodec = NULL;
|
||||
UnLockSubtitles();
|
||||
UnLockDecoder();
|
||||
}
|
||||
|
||||
void OMXPlayerVideo::Flush()
|
||||
{
|
||||
Lock();
|
||||
LockDecoder();
|
||||
m_flush = true;
|
||||
while (!m_packets.empty())
|
||||
{
|
||||
OMXPacket *pkt = m_packets.front();
|
||||
m_packets.pop_front();
|
||||
OMXReader::FreePacket(pkt);
|
||||
}
|
||||
m_iCurrentPts = DVD_NOPTS_VALUE;
|
||||
m_cached_size = 0;
|
||||
if(m_decoder)
|
||||
m_decoder->Reset();
|
||||
m_syncclock = true;
|
||||
UnLockDecoder();
|
||||
FlushSubtitles();
|
||||
UnLock();
|
||||
}
|
||||
|
||||
bool OMXPlayerVideo::AddPacket(OMXPacket *pkt)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if(!pkt)
|
||||
return ret;
|
||||
|
||||
if(m_bStop || m_bAbort)
|
||||
return ret;
|
||||
|
||||
if((m_cached_size + pkt->size) < MAX_DATA_SIZE)
|
||||
{
|
||||
Lock();
|
||||
m_cached_size += pkt->size;
|
||||
m_packets.push_back(pkt);
|
||||
UnLock();
|
||||
ret = true;
|
||||
pthread_cond_broadcast(&m_packet_cond);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool OMXPlayerVideo::OpenDecoder()
|
||||
{
|
||||
if (m_hints.fpsrate && m_hints.fpsscale)
|
||||
m_fps = DVD_TIME_BASE / OMXReader::NormalizeFrameduration((double)DVD_TIME_BASE * m_hints.fpsscale / m_hints.fpsrate);
|
||||
else
|
||||
m_fps = 25;
|
||||
|
||||
if( m_fps > 100 || m_fps < 5 )
|
||||
{
|
||||
printf("Invalid framerate %d, using forced 25fps and just trust timestamps\n", (int)m_fps);
|
||||
m_fps = 25;
|
||||
}
|
||||
|
||||
m_frametime = (double)DVD_TIME_BASE / m_fps;
|
||||
|
||||
m_decoder = new COMXVideo();
|
||||
if(!m_decoder->Open(m_hints, m_av_clock, m_Deinterlace, m_hdmi_clock_sync))
|
||||
{
|
||||
CloseDecoder();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Video codec %s width %d height %d profile %d fps %f\n",
|
||||
m_decoder->GetDecoderName().c_str() , m_hints.width, m_hints.height, m_hints.profile, m_fps);
|
||||
}
|
||||
|
||||
if(m_av_clock)
|
||||
m_av_clock->SetRefreshRate(m_fps);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OMXPlayerVideo::CloseDecoder()
|
||||
{
|
||||
if(m_decoder)
|
||||
delete m_decoder;
|
||||
m_decoder = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
int OMXPlayerVideo::GetDecoderBufferSize()
|
||||
{
|
||||
if(m_decoder)
|
||||
return m_decoder->GetInputBufferSize();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int OMXPlayerVideo::GetDecoderFreeSpace()
|
||||
{
|
||||
if(m_decoder)
|
||||
return m_decoder->GetFreeSpace();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OMXPlayerVideo::WaitCompletion()
|
||||
{
|
||||
if(!m_decoder)
|
||||
return;
|
||||
|
||||
while(true)
|
||||
{
|
||||
Lock();
|
||||
if(m_packets.empty())
|
||||
{
|
||||
UnLock();
|
||||
break;
|
||||
}
|
||||
UnLock();
|
||||
OMXClock::OMXSleep(50);
|
||||
}
|
||||
|
||||
m_decoder->WaitCompletion();
|
||||
}
|
||||
|
||||
void OMXPlayerVideo::SetSpeed(int speed)
|
||||
{
|
||||
m_speed = speed;
|
||||
}
|
||||
|
||||
CStdString OMXPlayerVideo::GetText()
|
||||
{
|
||||
OMXPacket *pkt = NULL;
|
||||
CStdString strSubtitle = "";
|
||||
|
||||
LockSubtitles();
|
||||
if (!m_subtitle_packets.empty())
|
||||
{
|
||||
pkt = m_subtitle_packets.front();
|
||||
if(!m_overlays.empty())
|
||||
{
|
||||
COMXOverlay *overlay = m_overlays.front();
|
||||
double now = m_av_clock->GetClock();
|
||||
double iPTSStartTime = pkt->pts;
|
||||
double iPTSStopTime = (overlay->iPTSStartTime > 0) ? iPTSStartTime + (overlay->iPTSStopTime - overlay->iPTSStartTime) : 0LL;
|
||||
|
||||
if((iPTSStartTime <= now)
|
||||
&& (iPTSStopTime >= now || iPTSStopTime == 0LL))
|
||||
{
|
||||
COMXOverlayText::CElement* e = ((COMXOverlayText*)overlay)->m_pHead;
|
||||
while (e)
|
||||
{
|
||||
if (e->IsElementType(COMXOverlayText::ELEMENT_TYPE_TEXT))
|
||||
{
|
||||
COMXOverlayText::CElementText* t = (COMXOverlayText::CElementText*)e;
|
||||
strSubtitle += t->m_text;
|
||||
strSubtitle += "\n";
|
||||
}
|
||||
e = e->pNext;
|
||||
}
|
||||
}
|
||||
else if(iPTSStopTime < now)
|
||||
{
|
||||
m_subtitle_packets.pop_front();
|
||||
m_overlays.pop_front();
|
||||
delete overlay;
|
||||
OMXReader::FreePacket(pkt);
|
||||
}
|
||||
}
|
||||
}
|
||||
UnLockSubtitles();
|
||||
|
||||
return strSubtitle;
|
||||
}
|
||||
128
OMXPlayerVideo.h
Normal file
128
OMXPlayerVideo.h
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _OMX_PLAYERVIDEO_H_
|
||||
#define _OMX_PLAYERVIDEO_H_
|
||||
|
||||
#include "utils/StdString.h"
|
||||
#include "DllAvUtil.h"
|
||||
#include "DllAvFormat.h"
|
||||
#include "DllAvFilter.h"
|
||||
#include "DllAvCodec.h"
|
||||
#include "DllAvCore.h"
|
||||
|
||||
#include "OMXReader.h"
|
||||
#include "OMXClock.h"
|
||||
#include "OMXStreamInfo.h"
|
||||
#include "OMXVideo.h"
|
||||
#ifdef STANDALONE
|
||||
#include "OMXThread.h"
|
||||
#else
|
||||
#include "threads/Thread.h"
|
||||
#endif
|
||||
|
||||
#include <deque>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "OMXOverlayCodec.h"
|
||||
#include "OMXOverlayText.h"
|
||||
#include "OMXOverlayCodecText.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#ifdef STANDALONE
|
||||
class OMXPlayerVideo : public OMXThread
|
||||
#else
|
||||
class OMXPlayerVideo : public CThread
|
||||
#endif
|
||||
{
|
||||
protected:
|
||||
AVStream *m_pStream;
|
||||
int m_stream_id;
|
||||
std::deque<OMXPacket *> m_subtitle_packets;
|
||||
std::deque<OMXPacket *> m_packets;
|
||||
std::deque<COMXOverlay *> m_overlays;
|
||||
DllAvUtil m_dllAvUtil;
|
||||
DllAvCodec m_dllAvCodec;
|
||||
DllAvFormat m_dllAvFormat;
|
||||
bool m_open;
|
||||
COMXStreamInfo m_hints;
|
||||
double m_iCurrentPts;
|
||||
pthread_cond_t m_packet_cond;
|
||||
pthread_cond_t m_picture_cond;
|
||||
pthread_mutex_t m_lock;
|
||||
pthread_mutex_t m_subtitle;
|
||||
pthread_mutex_t m_lock_decoder;
|
||||
pthread_mutex_t m_lock_subtitle;
|
||||
OMXClock *m_av_clock;
|
||||
COMXVideo *m_decoder;
|
||||
float m_fps;
|
||||
double m_frametime;
|
||||
bool m_Deinterlace;
|
||||
bool m_bMpeg;
|
||||
int m_has_audio;
|
||||
bool m_bAbort;
|
||||
bool m_use_thread;
|
||||
bool m_flush;
|
||||
unsigned int m_cached_size;
|
||||
bool m_hdmi_clock_sync;
|
||||
double m_iVideoDelay;
|
||||
double m_pts;
|
||||
bool m_syncclock;
|
||||
int m_speed;
|
||||
double m_FlipTimeStamp; // time stamp of last flippage. used to play at a forced framerate
|
||||
double m_iSubtitleDelay;
|
||||
COMXOverlayCodec *m_pSubtitleCodec;
|
||||
|
||||
void Lock();
|
||||
void UnLock();
|
||||
void LockDecoder();
|
||||
void UnLockDecoder();
|
||||
void LockSubtitles();
|
||||
void UnLockSubtitles();
|
||||
private:
|
||||
public:
|
||||
OMXPlayerVideo();
|
||||
~OMXPlayerVideo();
|
||||
bool Open(COMXStreamInfo &hints, OMXClock *av_clock, bool deinterlace, bool mpeg, int has_audio, bool hdmi_clock_sync, bool use_thread);
|
||||
bool Close();
|
||||
void Output(double pts);
|
||||
bool Decode(OMXPacket *pkt);
|
||||
void Process();
|
||||
void FlushSubtitles();
|
||||
void Flush();
|
||||
bool AddPacket(OMXPacket *pkt);
|
||||
bool OpenDecoder();
|
||||
bool CloseDecoder();
|
||||
int GetDecoderBufferSize();
|
||||
int GetDecoderFreeSpace();
|
||||
double GetCurrentPTS() { return m_pts; };
|
||||
double GetFPS() { return m_fps; };
|
||||
unsigned int GetCached() { return m_cached_size; };
|
||||
void WaitCompletion();
|
||||
void SetDelay(double delay) { m_iVideoDelay = delay; }
|
||||
double GetDelay() { return m_iVideoDelay; }
|
||||
void SetSpeed(int iSpeed);
|
||||
double GetSubtitleDelay() { return m_iSubtitleDelay; }
|
||||
void SetSubtitleDelay(double delay) { m_iSubtitleDelay = delay; }
|
||||
CStdString GetText();
|
||||
};
|
||||
#endif
|
||||
1429
OMXReader.cpp
Normal file
1429
OMXReader.cpp
Normal file
File diff suppressed because it is too large
Load diff
202
OMXReader.h
Normal file
202
OMXReader.h
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _OMX_READER_H_
|
||||
#define _OMX_READER_H_
|
||||
|
||||
#include "utils/StdString.h"
|
||||
#include "DllAvUtil.h"
|
||||
#include "DllAvFormat.h"
|
||||
#include "DllAvFilter.h"
|
||||
#include "DllAvCodec.h"
|
||||
#include "DllAvCore.h"
|
||||
#include "OMXStreamInfo.h"
|
||||
#ifdef STANDALONE
|
||||
#include "OMXThread.h"
|
||||
#else
|
||||
#include "threads/Thread.h"
|
||||
#endif
|
||||
#include <queue>
|
||||
|
||||
#include "OMXStreamInfo.h"
|
||||
|
||||
#ifdef STANDALONE
|
||||
#include "File.h"
|
||||
#else
|
||||
#include "xbmc/filesystem/File.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
using namespace XFILE;
|
||||
using namespace std;
|
||||
|
||||
#define MAX_OMX_CHAPTERS 64
|
||||
|
||||
#define MAX_OMX_STREAMS 100
|
||||
|
||||
#define OMX_PLAYSPEED_PAUSE 0
|
||||
#define OMX_PLAYSPEED_NORMAL 1
|
||||
|
||||
#ifndef FFMPEG_FILE_BUFFER_SIZE
|
||||
#define FFMPEG_FILE_BUFFER_SIZE 32768 // default reading size for ffmpeg
|
||||
#endif
|
||||
#ifndef MAX_STREAMS
|
||||
#define MAX_STREAMS 100
|
||||
#endif
|
||||
|
||||
typedef struct OMXChapter
|
||||
{
|
||||
std::string name;
|
||||
int64_t seekto_ms;
|
||||
double ts;
|
||||
} OMXChapter;
|
||||
|
||||
class OMXReader;
|
||||
|
||||
typedef struct OMXPacket
|
||||
{
|
||||
double pts; // pts in DVD_TIME_BASE
|
||||
double dts; // dts in DVD_TIME_BASE
|
||||
double now; // dts in DVD_TIME_BASE
|
||||
double duration; // duration in DVD_TIME_BASE if available
|
||||
int size;
|
||||
uint8_t *data;
|
||||
int stream_index;
|
||||
COMXStreamInfo hints;
|
||||
enum AVMediaType codec_type;
|
||||
} OMXPacket;
|
||||
|
||||
enum OMXStreamType
|
||||
{
|
||||
OMXSTREAM_NONE = 0,
|
||||
OMXSTREAM_AUDIO = 1,
|
||||
OMXSTREAM_VIDEO = 2,
|
||||
OMXSTREAM_SUBTITLE = 3
|
||||
};
|
||||
|
||||
typedef struct OMXStream
|
||||
{
|
||||
char language[4];
|
||||
std::string name;
|
||||
std::string codec_name;
|
||||
AVStream *stream;
|
||||
OMXStreamType type;
|
||||
int id;
|
||||
void *extradata;
|
||||
unsigned int extrasize;
|
||||
unsigned int index;
|
||||
COMXStreamInfo hints;
|
||||
} OMXStream;
|
||||
|
||||
class OMXReader
|
||||
{
|
||||
protected:
|
||||
int m_video_index;
|
||||
int m_audio_index;
|
||||
int m_subtitle_index;
|
||||
int m_video_count;
|
||||
int m_audio_count;
|
||||
int m_subtitle_count;
|
||||
DllAvUtil m_dllAvUtil;
|
||||
DllAvCodec m_dllAvCodec;
|
||||
DllAvFormat m_dllAvFormat;
|
||||
bool m_open;
|
||||
CStdString m_filename;
|
||||
bool m_bMatroska;
|
||||
bool m_bAVI;
|
||||
bool m_bMpeg;
|
||||
XFILE::CFile *m_pFile;
|
||||
AVFormatContext *m_pFormatContext;
|
||||
ByteIOContext *m_ioContext;
|
||||
bool m_eof;
|
||||
OMXChapter m_chapters[MAX_OMX_CHAPTERS];
|
||||
OMXStream m_streams[MAX_STREAMS];
|
||||
int m_chapter_count;
|
||||
double m_iCurrentPts;
|
||||
int64_t m_seek_ms;
|
||||
int m_seek_req;
|
||||
int m_seek_flags;
|
||||
int m_speed;
|
||||
int64_t m_duration_ms;
|
||||
unsigned int m_program;
|
||||
void AddTimespecs(struct timespec &time, long millisecs);
|
||||
#ifdef STANDALONE
|
||||
void flush_packet_queue(AVFormatContext *s);
|
||||
void av_read_frame_flush(AVFormatContext *s);
|
||||
#endif
|
||||
pthread_mutex_t m_lock;
|
||||
void Lock();
|
||||
void UnLock();
|
||||
bool SetActiveStreamInternal(OMXStreamType type, unsigned int index);
|
||||
private:
|
||||
public:
|
||||
OMXReader();
|
||||
~OMXReader();
|
||||
bool Open(CStdString filename, bool dump_format);
|
||||
void ClearStreams();
|
||||
bool Close();
|
||||
void FlushRead();
|
||||
bool SeekTime(int64_t seek_ms, int seek_flags, double *startpts);
|
||||
AVMediaType PacketType(OMXPacket *pkt);
|
||||
OMXPacket *Read();
|
||||
void Process();
|
||||
bool GetStreams();
|
||||
void AddStream(int id);
|
||||
bool IsActive(int stream_index);
|
||||
bool IsActive(OMXStreamType type, int stream_index);
|
||||
bool GetHints(AVStream *stream, COMXStreamInfo *hints);
|
||||
bool GetHints(OMXStreamType type, unsigned int index, COMXStreamInfo &hints);
|
||||
bool GetHints(OMXStreamType type, COMXStreamInfo &hints);
|
||||
bool IsEof();
|
||||
int AudioStreamCount() { return m_audio_count; };
|
||||
int VideoStreamCount() { return m_video_count; };
|
||||
int SubtitleStreamCount() { return m_subtitle_count; };
|
||||
bool SetActiveStream(OMXStreamType type, unsigned int index);
|
||||
int GetChapterCount() { return m_chapter_count; };
|
||||
OMXChapter GetChapter(unsigned int chapter) { return m_chapters[(chapter > MAX_OMX_CHAPTERS) ? MAX_OMX_CHAPTERS : chapter]; };
|
||||
static void FreePacket(OMXPacket *pkt);
|
||||
static OMXPacket *AllocPacket(int size);
|
||||
void SetSpeed(int iSpeed);
|
||||
void UpdateCurrentPTS();
|
||||
double ConvertTimestamp(int64_t pts, int den, int num);
|
||||
double ConvertTimestamp(int64_t pts, AVRational *time_base);
|
||||
int GetChapter();
|
||||
void GetChapterName(std::string& strChapterName);
|
||||
bool SeekChapter(int chapter, double* startpts);
|
||||
bool GetAudioIndex() { return m_audio_index; };
|
||||
bool GetSubtitleIndex() { return m_subtitle_index; };
|
||||
int GetStreamLength();
|
||||
static double NormalizeFrameduration(double frameduration);
|
||||
bool IsMpegVideo() { return m_bMpeg; };
|
||||
bool IsMatroska() { return m_bMatroska; };
|
||||
CStdString GetCodecName(OMXStreamType type);
|
||||
CStdString GetCodecName(OMXStreamType type, unsigned int index);
|
||||
CStdString GetStreamCodecName(AVStream *stream);
|
||||
CStdString GetStreamLanguage(OMXStreamType type, unsigned int index);
|
||||
CStdString GetStreamName(OMXStreamType type, unsigned int index);
|
||||
int64_t GetDuration() { return m_duration_ms; };
|
||||
CStdString GetStreamType(OMXStreamType type, unsigned int index);
|
||||
#ifndef STANDALONE
|
||||
int GetSourceBitrate();
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
71
OMXStreamInfo.cpp
Normal file
71
OMXStreamInfo.cpp
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "OMXStreamInfo.h"
|
||||
|
||||
COMXStreamInfo::COMXStreamInfo()
|
||||
{
|
||||
extradata = NULL;
|
||||
Clear();
|
||||
}
|
||||
|
||||
COMXStreamInfo::~COMXStreamInfo()
|
||||
{
|
||||
//if( extradata && extrasize ) free(extradata);
|
||||
|
||||
extradata = NULL;
|
||||
extrasize = 0;
|
||||
}
|
||||
|
||||
|
||||
void COMXStreamInfo::Clear()
|
||||
{
|
||||
codec = CODEC_ID_NONE;
|
||||
software = false;
|
||||
codec_tag = 0;
|
||||
|
||||
//if( extradata && extrasize ) free(extradata);
|
||||
|
||||
extradata = NULL;
|
||||
extrasize = 0;
|
||||
|
||||
fpsscale = 0;
|
||||
fpsrate = 0;
|
||||
height = 0;
|
||||
width = 0;
|
||||
aspect = 0.0;
|
||||
vfr = false;
|
||||
stills = false;
|
||||
level = 0;
|
||||
profile = 0;
|
||||
ptsinvalid = false;
|
||||
|
||||
channels = 0;
|
||||
samplerate = 0;
|
||||
blockalign = 0;
|
||||
bitrate = 0;
|
||||
bitspersample = 0;
|
||||
|
||||
identifier = 0;
|
||||
|
||||
framesize = 0;
|
||||
syncword = 0;
|
||||
}
|
||||
80
OMXStreamInfo.h
Normal file
80
OMXStreamInfo.h
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if (defined HAVE_CONFIG_H) && (!defined WIN32)
|
||||
#include "config.h"
|
||||
#endif
|
||||
#ifndef _LINUX
|
||||
enum CodecID;
|
||||
#else
|
||||
extern "C" {
|
||||
#include "libavcodec/avcodec.h"
|
||||
}
|
||||
#endif
|
||||
|
||||
class CDemuxStream;
|
||||
|
||||
class COMXStreamInfo
|
||||
{
|
||||
public:
|
||||
COMXStreamInfo();
|
||||
|
||||
~COMXStreamInfo();
|
||||
|
||||
void Clear(); // clears current information
|
||||
|
||||
CodecID codec;
|
||||
bool software; //force software decoding
|
||||
|
||||
|
||||
// VIDEO
|
||||
int fpsscale; // scale of 1000 and a rate of 29970 will result in 29.97 fps
|
||||
int fpsrate;
|
||||
int height; // height of the stream reported by the demuxer
|
||||
int width; // width of the stream reported by the demuxer
|
||||
float aspect; // display aspect as reported by demuxer
|
||||
bool vfr; // variable framerate
|
||||
bool stills; // there may be odd still frames in video
|
||||
int level; // encoder level of the stream reported by the decoder. used to qualify hw decoders.
|
||||
int profile; // encoder profile of the stream reported by the decoder. used to qualify hw decoders.
|
||||
bool ptsinvalid; // pts cannot be trusted (avi's).
|
||||
|
||||
// AUDIO
|
||||
int channels;
|
||||
int samplerate;
|
||||
int bitrate;
|
||||
int blockalign;
|
||||
int bitspersample;
|
||||
|
||||
// SUBTITLE
|
||||
int identifier;
|
||||
|
||||
// CODEC EXTRADATA
|
||||
void* extradata; // extra data for codec to use
|
||||
unsigned int extrasize; // size of extra data
|
||||
unsigned int codec_tag; // extra identifier hints for decoding
|
||||
|
||||
/* ac3/dts indof */
|
||||
unsigned int framesize;
|
||||
uint32_t syncword;
|
||||
};
|
||||
261
OMXSubtitleTagSami.cpp
Normal file
261
OMXSubtitleTagSami.cpp
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "OMXSubtitleTagSami.h"
|
||||
//#include "DVDSubtitleStream.h"
|
||||
#include "linux/PlatformDefs.h"
|
||||
#include "OMXOverlayText.h"
|
||||
#include "utils/RegExp.h"
|
||||
|
||||
COMXSubtitleTagSami::~COMXSubtitleTagSami()
|
||||
{
|
||||
delete m_tags;
|
||||
delete m_tagOptions;
|
||||
}
|
||||
|
||||
bool COMXSubtitleTagSami::Init()
|
||||
{
|
||||
m_tags = new CRegExp(true);
|
||||
if (!m_tags->RegComp("(<[^>]*>|\\{[^\\}]*\\})"))
|
||||
return false;
|
||||
|
||||
m_tagOptions = new CRegExp(true);
|
||||
if (!m_tagOptions->RegComp("([a-z]+)[ \t]*=[ \t]*(?:[\"'])?([^\"'> ]+)(?:[\"'])?(?:>)?"))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void COMXSubtitleTagSami::ConvertLine(COMXOverlayText* pOverlay, const char* line, int len, const char* lang)
|
||||
{
|
||||
CStdStringA strUTF8;
|
||||
strUTF8.assign(line, len);
|
||||
strUTF8.Trim();
|
||||
|
||||
int pos = 0;
|
||||
int del_start = 0;
|
||||
while ((pos=m_tags->RegFind(strUTF8.c_str(), pos)) >= 0)
|
||||
{
|
||||
// Parse Tags
|
||||
CStdString fullTag = m_tags->GetMatch(0);
|
||||
fullTag.ToLower();
|
||||
strUTF8.erase(pos, fullTag.length());
|
||||
if (fullTag == "<b>" || fullTag == "{\\b1}")
|
||||
{
|
||||
m_flag[FLAG_BOLD] = true;
|
||||
strUTF8.insert(pos, "[B]");
|
||||
pos += 3;
|
||||
}
|
||||
else if ((fullTag == "</b>" || fullTag == "{\\b0}") && m_flag[FLAG_BOLD])
|
||||
{
|
||||
m_flag[FLAG_BOLD] = false;
|
||||
strUTF8.insert(pos, "[/B]");
|
||||
pos += 4;
|
||||
}
|
||||
else if (fullTag == "<i>" || fullTag == "{\\i1}")
|
||||
{
|
||||
m_flag[FLAG_ITALIC] = true;
|
||||
strUTF8.insert(pos, "[I]");
|
||||
pos += 3;
|
||||
}
|
||||
else if ((fullTag == "</i>" || fullTag == "{\\i0}") && m_flag[FLAG_ITALIC])
|
||||
{
|
||||
m_flag[FLAG_ITALIC] = false;
|
||||
strUTF8.insert(pos, "[/I]");
|
||||
pos += 4;
|
||||
}
|
||||
else if ((fullTag == "</font>" || fullTag == "{\\c}") && m_flag[FLAG_COLOR])
|
||||
{
|
||||
m_flag[FLAG_COLOR] = false;
|
||||
strUTF8.insert(pos, "[/COLOR]");
|
||||
pos += 8;
|
||||
}
|
||||
else if (fullTag.Left(5) == "{\\c&h" || fullTag.Left(6) == "{\\1c&h")
|
||||
{
|
||||
m_flag[FLAG_COLOR] = true;
|
||||
CStdString tempColorTag = "[COLOR FF";
|
||||
CStdString tagOptionValue;
|
||||
if (fullTag.Left(5) == "{\\c&h")
|
||||
tagOptionValue = fullTag.substr(5,6);
|
||||
else
|
||||
tagOptionValue = fullTag.substr(6,6);
|
||||
tempColorTag += tagOptionValue.substr(4,2);
|
||||
tempColorTag += tagOptionValue.substr(2,2);
|
||||
tempColorTag += tagOptionValue.substr(0,2);
|
||||
tempColorTag += "]";
|
||||
strUTF8.insert(pos, tempColorTag);
|
||||
pos += tempColorTag.length();
|
||||
}
|
||||
else if (fullTag.Left(5) == "<font")
|
||||
{
|
||||
int pos2 = 5;
|
||||
while ((pos2 = m_tagOptions->RegFind(fullTag.c_str(), pos2)) >= 0)
|
||||
{
|
||||
CStdString tagOptionName = m_tagOptions->GetMatch(1);
|
||||
CStdString tagOptionValue = m_tagOptions->GetMatch(2);
|
||||
pos2 += tagOptionName.length() + tagOptionValue.length();
|
||||
if (tagOptionName == "color")
|
||||
{
|
||||
m_flag[FLAG_COLOR] = true;
|
||||
CStdString tempColorTag = "[COLOR ";
|
||||
if (tagOptionValue[0] == '#')
|
||||
{
|
||||
tagOptionValue.erase(0, 1);
|
||||
tempColorTag += "FF";
|
||||
}
|
||||
else if( tagOptionValue.size() == 6 )
|
||||
{
|
||||
bool bHex = true;
|
||||
for( int i=0 ; i<6 ; i++ )
|
||||
{
|
||||
char temp = tagOptionValue[i];
|
||||
if( !(('0' <= temp && temp <= '9') ||
|
||||
('a' <= temp && temp <= 'f') ||
|
||||
('A' <= temp && temp <= 'F') ))
|
||||
{
|
||||
bHex = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( bHex ) tempColorTag += "FF";
|
||||
}
|
||||
tempColorTag += tagOptionValue;
|
||||
tempColorTag += "]";
|
||||
strUTF8.insert(pos, tempColorTag);
|
||||
pos += tempColorTag.length();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (lang && (fullTag.Left(3) == "<p "))
|
||||
{
|
||||
int pos2 = 3;
|
||||
while ((pos2 = m_tagOptions->RegFind(fullTag.c_str(), pos2)) >= 0)
|
||||
{
|
||||
CStdString tagOptionName = m_tagOptions->GetMatch(1);
|
||||
CStdString tagOptionValue = m_tagOptions->GetMatch(2);
|
||||
pos2 += tagOptionName.length() + tagOptionValue.length();
|
||||
if (tagOptionName == "class")
|
||||
{
|
||||
if (m_flag[FLAG_LANGUAGE])
|
||||
{
|
||||
strUTF8.erase(del_start, pos - del_start);
|
||||
pos = del_start;
|
||||
}
|
||||
if (!tagOptionValue.Compare(lang))
|
||||
{
|
||||
m_flag[FLAG_LANGUAGE] = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flag[FLAG_LANGUAGE] = true;
|
||||
del_start = pos;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (fullTag == "</p>" && m_flag[FLAG_LANGUAGE])
|
||||
{
|
||||
strUTF8.erase(del_start, pos - del_start);
|
||||
pos = del_start;
|
||||
m_flag[FLAG_LANGUAGE] = false;
|
||||
}
|
||||
else if (fullTag == "<br>" && !strUTF8.IsEmpty())
|
||||
{
|
||||
strUTF8.Insert(pos, "\n");
|
||||
pos += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(m_flag[FLAG_LANGUAGE])
|
||||
strUTF8.erase(del_start);
|
||||
|
||||
if (strUTF8.IsEmpty())
|
||||
return;
|
||||
|
||||
if( strUTF8[strUTF8.size()-1] == '\n' )
|
||||
strUTF8.Delete(strUTF8.size()-1);
|
||||
|
||||
// add a new text element to our container
|
||||
pOverlay->AddElement(new COMXOverlayText::CElementText(strUTF8.c_str()));
|
||||
}
|
||||
|
||||
void COMXSubtitleTagSami::CloseTag(COMXOverlayText* pOverlay)
|
||||
{
|
||||
if (m_flag[FLAG_BOLD])
|
||||
{
|
||||
pOverlay->AddElement(new COMXOverlayText::CElementText("[/B]"));
|
||||
m_flag[FLAG_BOLD] = false;
|
||||
}
|
||||
if (m_flag[FLAG_ITALIC])
|
||||
{
|
||||
pOverlay->AddElement(new COMXOverlayText::CElementText("[/I]"));
|
||||
m_flag[FLAG_ITALIC] = false;
|
||||
}
|
||||
if (m_flag[FLAG_COLOR])
|
||||
{
|
||||
pOverlay->AddElement(new COMXOverlayText::CElementText("[/COLOR]"));
|
||||
m_flag[FLAG_COLOR] = false;
|
||||
}
|
||||
m_flag[FLAG_LANGUAGE] = false;
|
||||
}
|
||||
|
||||
/*
|
||||
void COMXSubtitleTagSami::LoadHead(CDVDSubtitleStream* samiStream)
|
||||
{
|
||||
char line[1024];
|
||||
bool inSTYLE = false;
|
||||
CRegExp reg(true);
|
||||
if (!reg.RegComp("\\.([a-z]+)[ \t]*\\{[ \t]*name:([^;]*?);[ \t]*lang:([^;]*?);[ \t]*SAMIType:([^;]*?);[ \t]*\\}"))
|
||||
return;
|
||||
|
||||
while (samiStream->ReadLine(line, sizeof(line)))
|
||||
{
|
||||
if (!strnicmp(line, "<BODY>", 6))
|
||||
break;
|
||||
if (inSTYLE)
|
||||
{
|
||||
if (!strnicmp(line, "</STYLE>", 8))
|
||||
break;
|
||||
else
|
||||
{
|
||||
if (reg.RegFind(line) > -1)
|
||||
{
|
||||
SLangclass lc;
|
||||
lc.ID = reg.GetMatch(1);
|
||||
lc.Name = reg.GetMatch(2);
|
||||
lc.Lang = reg.GetMatch(3);
|
||||
lc.SAMIType = reg.GetMatch(4);
|
||||
lc.Name.Trim();
|
||||
lc.Lang.Trim();
|
||||
lc.SAMIType.Trim();
|
||||
m_Langclass.push_back(lc);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!strnicmp(line, "<STYLE TYPE=\"text/css\">", 23))
|
||||
inSTYLE = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
68
OMXSubtitleTagSami.h
Normal file
68
OMXSubtitleTagSami.h
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "utils/StdString.h"
|
||||
|
||||
#define FLAG_BOLD 0
|
||||
#define FLAG_ITALIC 1
|
||||
#define FLAG_COLOR 2
|
||||
#define FLAG_LANGUAGE 3
|
||||
|
||||
class COMXOverlayText;
|
||||
class CDVDSubtitleStream;
|
||||
class CRegExp;
|
||||
|
||||
class COMXSubtitleTagSami
|
||||
{
|
||||
public:
|
||||
COMXSubtitleTagSami()
|
||||
{
|
||||
m_tags = NULL;
|
||||
m_tagOptions = NULL;
|
||||
m_flag[FLAG_BOLD] = false;
|
||||
m_flag[FLAG_ITALIC] = false;
|
||||
m_flag[FLAG_COLOR] = false;
|
||||
m_flag[FLAG_LANGUAGE] = false; //set to true when classID != lang
|
||||
}
|
||||
virtual ~COMXSubtitleTagSami();
|
||||
bool Init();
|
||||
void ConvertLine(COMXOverlayText* pOverlay, const char* line, int len, const char* lang = NULL);
|
||||
void CloseTag(COMXOverlayText* pOverlay);
|
||||
//void LoadHead(CDVDSubtitleStream* samiStream);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CStdString ID;
|
||||
CStdString Name;
|
||||
CStdString Lang;
|
||||
CStdString SAMIType;
|
||||
} SLangclass;
|
||||
|
||||
std::vector<SLangclass> m_Langclass;
|
||||
|
||||
private:
|
||||
CRegExp *m_tags;
|
||||
CRegExp *m_tagOptions;
|
||||
bool m_flag[4];
|
||||
};
|
||||
|
||||
132
OMXThread.cpp
Normal file
132
OMXThread.cpp
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#if (defined HAVE_CONFIG_H) && (!defined WIN32)
|
||||
#include "config.h"
|
||||
#elif defined(_WIN32)
|
||||
#include "system.h"
|
||||
#endif
|
||||
|
||||
#include "OMXThread.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "utils/log.h"
|
||||
|
||||
#ifdef CLASSNAME
|
||||
#undef CLASSNAME
|
||||
#endif
|
||||
#define CLASSNAME "OMXThread"
|
||||
|
||||
OMXThread::OMXThread()
|
||||
{
|
||||
pthread_mutex_init(&m_lock, NULL);
|
||||
pthread_attr_setdetachstate(&m_tattr, PTHREAD_CREATE_JOINABLE);
|
||||
pthread_attr_init(&m_tattr);
|
||||
m_thread = 0;
|
||||
m_bStop = false;
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
OMXThread::~OMXThread()
|
||||
{
|
||||
pthread_mutex_destroy(&m_lock);
|
||||
pthread_attr_destroy(&m_tattr);
|
||||
}
|
||||
|
||||
bool OMXThread::StopThread()
|
||||
{
|
||||
if(!m_running)
|
||||
{
|
||||
CLog::Log(LOGDEBUG, "%s::%s - No thread running\n", CLASSNAME, __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_bStop = true;
|
||||
pthread_join(m_thread, NULL);
|
||||
m_running = false;
|
||||
|
||||
m_thread = 0;
|
||||
|
||||
CLog::Log(LOGDEBUG, "%s::%s - Thread stopped\n", CLASSNAME, __func__);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OMXThread::Create()
|
||||
{
|
||||
if(m_running)
|
||||
{
|
||||
CLog::Log(LOGERROR, "%s::%s - Thread already running\n", CLASSNAME, __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_bStop = false;
|
||||
m_running = true;
|
||||
|
||||
pthread_create(&m_thread, &m_tattr, &OMXThread::Run, this);
|
||||
|
||||
CLog::Log(LOGDEBUG, "%s::%s - Thread with id %d started\n", CLASSNAME, __func__, (int)m_thread);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OMXThread::Running()
|
||||
{
|
||||
return m_running;
|
||||
}
|
||||
|
||||
pthread_t OMXThread::ThreadHandle()
|
||||
{
|
||||
return m_thread;
|
||||
}
|
||||
|
||||
void *OMXThread::Run(void *arg)
|
||||
{
|
||||
OMXThread *thread = static_cast<OMXThread *>(arg);
|
||||
thread->Process();
|
||||
|
||||
CLog::Log(LOGDEBUG, "%s::%s - Exited thread with id %d\n", CLASSNAME, __func__, (int)thread->ThreadHandle());
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
void OMXThread::Lock()
|
||||
{
|
||||
if(!m_running)
|
||||
{
|
||||
CLog::Log(LOGDEBUG, "%s::%s - No thread running\n", CLASSNAME, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&m_lock);
|
||||
}
|
||||
|
||||
void OMXThread::UnLock()
|
||||
{
|
||||
if(!m_running)
|
||||
{
|
||||
CLog::Log(LOGDEBUG, "%s::%s - No thread running\n", CLASSNAME, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&m_lock);
|
||||
}
|
||||
|
||||
49
OMXThread.h
Normal file
49
OMXThread.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _OMX_THREAD_H_
|
||||
#define _OMX_THREAD_H_
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
class OMXThread
|
||||
{
|
||||
protected:
|
||||
pthread_attr_t m_tattr;
|
||||
struct sched_param m_sched_param;
|
||||
pthread_mutex_t m_lock;
|
||||
pthread_t m_thread;
|
||||
volatile bool m_running;
|
||||
volatile bool m_bStop;
|
||||
private:
|
||||
static void *Run(void *arg);
|
||||
public:
|
||||
OMXThread();
|
||||
~OMXThread();
|
||||
bool Create();
|
||||
virtual void Process() = 0;
|
||||
bool Running();
|
||||
pthread_t ThreadHandle();
|
||||
bool StopThread();
|
||||
void Lock();
|
||||
void UnLock();
|
||||
};
|
||||
#endif
|
||||
1090
OMXVideo.cpp
Normal file
1090
OMXVideo.cpp
Normal file
File diff suppressed because it is too large
Load diff
106
OMXVideo.h
Normal file
106
OMXVideo.h
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
#pragma once
|
||||
/*
|
||||
* Copyright (C) 2010 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(HAVE_OMXLIB)
|
||||
|
||||
#include "OMXCore.h"
|
||||
#include "OMXStreamInfo.h"
|
||||
|
||||
#include <IL/OMX_Video.h>
|
||||
|
||||
#include "BitstreamConverter.h"
|
||||
|
||||
#include "OMXClock.h"
|
||||
#include "OMXReader.h"
|
||||
|
||||
#include "guilib/Geometry.h"
|
||||
|
||||
|
||||
#define VIDEO_BUFFERS 60
|
||||
|
||||
#define CLASSNAME "COMXVideo"
|
||||
|
||||
class DllAvUtil;
|
||||
class DllAvFormat;
|
||||
class COMXVideo
|
||||
{
|
||||
public:
|
||||
COMXVideo();
|
||||
~COMXVideo();
|
||||
|
||||
// Required overrides
|
||||
bool SendDecoderConfig();
|
||||
bool Open(COMXStreamInfo &hints, OMXClock *clock, bool deinterlace = false, bool hdmi_clock_sync = false);
|
||||
void Close(void);
|
||||
unsigned int GetFreeSpace();
|
||||
unsigned int GetSize();
|
||||
OMXPacket *GetText();
|
||||
int DecodeText(uint8_t *pData, int iSize, double dts, double pts);
|
||||
int Decode(uint8_t *pData, int iSize, double dts, double pts);
|
||||
void Reset(void);
|
||||
void SetDropState(bool bDrop);
|
||||
bool Pause();
|
||||
bool Resume();
|
||||
CStdString GetDecoderName() { return m_video_codec_name; };
|
||||
void SetVideoRect(const CRect& SrcRect, const CRect& DestRect);
|
||||
int GetInputBufferSize();
|
||||
void WaitCompletion();
|
||||
protected:
|
||||
// Video format
|
||||
bool m_drop_state;
|
||||
unsigned int m_decoded_width;
|
||||
unsigned int m_decoded_height;
|
||||
|
||||
OMX_VIDEO_CODINGTYPE m_codingType;
|
||||
|
||||
COMXCoreComponent m_omx_text;
|
||||
COMXCoreComponent m_omx_decoder;
|
||||
COMXCoreComponent m_omx_render;
|
||||
COMXCoreComponent m_omx_sched;
|
||||
COMXCoreComponent m_omx_image_fx;
|
||||
COMXCoreComponent *m_omx_clock;
|
||||
OMXClock *m_av_clock;
|
||||
|
||||
COMXCoreTunel m_omx_tunnel_text;
|
||||
COMXCoreTunel m_omx_tunnel_decoder;
|
||||
COMXCoreTunel m_omx_tunnel_clock;
|
||||
COMXCoreTunel m_omx_tunnel_sched;
|
||||
COMXCoreTunel m_omx_tunnel_image_fx;
|
||||
bool m_is_open;
|
||||
|
||||
bool m_Pause;
|
||||
bool m_setStartTime;
|
||||
|
||||
uint8_t *m_extradata;
|
||||
int m_extrasize;
|
||||
|
||||
CBitstreamConverter *m_converter;
|
||||
bool m_video_convert;
|
||||
CStdString m_video_codec_name;
|
||||
|
||||
bool m_deinterlace;
|
||||
bool m_hdmi_clock_sync;
|
||||
bool m_first_frame;
|
||||
bool m_first_text;
|
||||
};
|
||||
|
||||
#endif
|
||||
65
RBP.h
Normal file
65
RBP.h
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
#pragma once
|
||||
/*
|
||||
* Copyright (C) 2005-2009 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
#define _HAVE_SBRK 1
|
||||
#define HAVE_CMAKE_CONFIG 1
|
||||
#define _REENTRANT 1
|
||||
#ifndef VCHI_BULK_ALIGN
|
||||
#define VCHI_BULK_ALIGN 1
|
||||
#endif
|
||||
#ifndef VCHI_BULK_GRANULARITY
|
||||
#define VCHI_BULK_GRANULARITY 1
|
||||
#endif
|
||||
*/
|
||||
//#define OMX_SKIP64BIT
|
||||
#ifndef USE_VCHIQ_ARM
|
||||
#define USE_VCHIQ_ARM
|
||||
#endif
|
||||
#ifndef __VIDEOCORE4__
|
||||
#define __VIDEOCORE4__
|
||||
#endif
|
||||
#ifndef HAVE_VMCS_CONFIG
|
||||
#define HAVE_VMCS_CONFIG
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_LIBBCM_HOST
|
||||
#define HAVE_LIBBCM_HOST
|
||||
#endif
|
||||
|
||||
#include "DllBCM.h"
|
||||
|
||||
class CRBP
|
||||
{
|
||||
public:
|
||||
CRBP();
|
||||
~CRBP();
|
||||
|
||||
bool Initialize();
|
||||
void Deinitialize();
|
||||
|
||||
private:
|
||||
DllBcmHost *m_DllBcmHost;
|
||||
bool m_initialized;
|
||||
};
|
||||
|
||||
extern CRBP g_RBP;
|
||||
45
README
Normal file
45
README
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
What is it :
|
||||
|
||||
omxplayer is a commandline OMX player for the Rasipberry PI.
|
||||
|
||||
It was developed as a testbed for the XBMC Raspberry PI implementation
|
||||
and is quite handy to use standalone.
|
||||
|
||||
Using it :
|
||||
|
||||
Usage: omxplayer [OPTIONS] [FILE]
|
||||
Options :
|
||||
-h / --help print this help
|
||||
-a / --alang language audio language : e.g. ger
|
||||
-n / --aidx index audio stream index : e.g. 1
|
||||
-o / --adev device audio out device : e.g. hdmi/local
|
||||
-i / --info dump stream format and exit
|
||||
-s / --stats pts and buffer stats
|
||||
-p / --passthrough audio passthrough
|
||||
-d / --deinterlace deinterlacing
|
||||
-w / --hw hw audio decoding
|
||||
-3 / --3d switch tv into 3d mode
|
||||
-y / --hdmiclocksync adjust display refresh rate to match video
|
||||
-t / --sid index show subtitle with index
|
||||
|
||||
For example: ./omxplayer -p -o hdmi test.mkv
|
||||
|
||||
Compiling :
|
||||
|
||||
You need the content of your sdcard somewhere mounted or copied.
|
||||
There might be development headers to install on the running PI system
|
||||
for the crosscompiling.
|
||||
|
||||
Edit Makefile.include and change the settings according your locations.
|
||||
|
||||
You can also compile it on the PI the native way ;)
|
||||
|
||||
Run :
|
||||
|
||||
make ffmpeg
|
||||
make
|
||||
make dist
|
||||
|
||||
Installing :
|
||||
copy over omxplayer-dist/* to the PI /
|
||||
|
||||
43
cores/IAudioCallback.h
Normal file
43
cores/IAudioCallback.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
// IAudioCallback.h: interface for the IAudioCallback class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(AFX_IAUDIOCALLBACK_H__5A6AC7CF_C60E_45B9_8113_599F036FBBF8__INCLUDED_)
|
||||
#define AFX_IAUDIOCALLBACK_H__5A6AC7CF_C60E_45B9_8113_599F036FBBF8__INCLUDED_
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
class IAudioCallback
|
||||
{
|
||||
public:
|
||||
IAudioCallback() {};
|
||||
virtual ~IAudioCallback() {};
|
||||
virtual void OnInitialize(int iChannels, int iSamplesPerSec, int iBitsPerSample) = 0;
|
||||
virtual void OnAudioData(const unsigned char* pAudioData, int iAudioDataLength) = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif // !defined(AFX_IAUDIOCALLBACK_H__5A6AC7CF_C60E_45B9_8113_599F036FBBF8__INCLUDED_)
|
||||
173
guilib/Geometry.h
Normal file
173
guilib/Geometry.h
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __GNUC__
|
||||
// under gcc, inline will only take place if optimizations are applied (-O). this will force inline even whith optimizations.
|
||||
#define XBMC_FORCE_INLINE __attribute__((always_inline))
|
||||
#else
|
||||
#define XBMC_FORCE_INLINE
|
||||
#endif
|
||||
#include <algorithm>
|
||||
|
||||
class CPoint
|
||||
{
|
||||
public:
|
||||
CPoint()
|
||||
{
|
||||
x = 0; y = 0;
|
||||
};
|
||||
|
||||
CPoint(float a, float b)
|
||||
{
|
||||
x = a;
|
||||
y = b;
|
||||
};
|
||||
|
||||
CPoint operator+(const CPoint &point) const
|
||||
{
|
||||
CPoint ans;
|
||||
ans.x = x + point.x;
|
||||
ans.y = y + point.y;
|
||||
return ans;
|
||||
};
|
||||
|
||||
const CPoint &operator+=(const CPoint &point)
|
||||
{
|
||||
x += point.x;
|
||||
y += point.y;
|
||||
return *this;
|
||||
};
|
||||
|
||||
CPoint operator-(const CPoint &point) const
|
||||
{
|
||||
CPoint ans;
|
||||
ans.x = x - point.x;
|
||||
ans.y = y - point.y;
|
||||
return ans;
|
||||
};
|
||||
|
||||
const CPoint &operator-=(const CPoint &point)
|
||||
{
|
||||
x -= point.x;
|
||||
y -= point.y;
|
||||
return *this;
|
||||
};
|
||||
|
||||
float x, y;
|
||||
};
|
||||
|
||||
class CRect
|
||||
{
|
||||
public:
|
||||
CRect() { x1 = y1 = x2 = y2 = 0;};
|
||||
CRect(float left, float top, float right, float bottom) { x1 = left; y1 = top; x2 = right; y2 = bottom; };
|
||||
|
||||
void SetRect(float left, float top, float right, float bottom) { x1 = left; y1 = top; x2 = right; y2 = bottom; };
|
||||
|
||||
bool PtInRect(const CPoint &point) const
|
||||
{
|
||||
if (x1 <= point.x && point.x <= x2 && y1 <= point.y && point.y <= y2)
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
inline const CRect &operator -=(const CPoint &point) XBMC_FORCE_INLINE
|
||||
{
|
||||
x1 -= point.x;
|
||||
y1 -= point.y;
|
||||
x2 -= point.x;
|
||||
y2 -= point.y;
|
||||
return *this;
|
||||
};
|
||||
|
||||
inline const CRect &operator +=(const CPoint &point) XBMC_FORCE_INLINE
|
||||
{
|
||||
x1 += point.x;
|
||||
y1 += point.y;
|
||||
x2 += point.x;
|
||||
y2 += point.y;
|
||||
return *this;
|
||||
};
|
||||
|
||||
const CRect &Intersect(const CRect &rect)
|
||||
{
|
||||
x1 = clamp_range(x1, rect.x1, rect.x2);
|
||||
x2 = clamp_range(x2, rect.x1, rect.x2);
|
||||
y1 = clamp_range(y1, rect.y1, rect.y2);
|
||||
y2 = clamp_range(y2, rect.y1, rect.y2);
|
||||
return *this;
|
||||
};
|
||||
|
||||
const CRect &Union(const CRect &rect)
|
||||
{
|
||||
if (IsEmpty())
|
||||
*this = rect;
|
||||
else if (!rect.IsEmpty())
|
||||
{
|
||||
x1 = std::min(x1,rect.x1);
|
||||
y1 = std::min(y1,rect.y1);
|
||||
|
||||
x2 = std::max(x2,rect.x2);
|
||||
y2 = std::max(y2,rect.y2);
|
||||
}
|
||||
|
||||
return *this;
|
||||
};
|
||||
|
||||
inline bool IsEmpty() const XBMC_FORCE_INLINE
|
||||
{
|
||||
return (x2 - x1) * (y2 - y1) == 0;
|
||||
};
|
||||
|
||||
inline float Width() const XBMC_FORCE_INLINE
|
||||
{
|
||||
return x2 - x1;
|
||||
};
|
||||
|
||||
inline float Height() const XBMC_FORCE_INLINE
|
||||
{
|
||||
return y2 - y1;
|
||||
};
|
||||
|
||||
inline float Area() const XBMC_FORCE_INLINE
|
||||
{
|
||||
return Width() * Height();
|
||||
};
|
||||
|
||||
bool operator !=(const CRect &rect) const
|
||||
{
|
||||
if (x1 != rect.x1) return true;
|
||||
if (x2 != rect.x2) return true;
|
||||
if (y1 != rect.y1) return true;
|
||||
if (y2 != rect.y2) return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
float x1, y1, x2, y2;
|
||||
private:
|
||||
inline static float clamp_range(float x, float l, float h) XBMC_FORCE_INLINE
|
||||
{
|
||||
return (x > h) ? h : ((x < l) ? l : x);
|
||||
}
|
||||
};
|
||||
|
||||
50
linux/ConvUtils.h
Normal file
50
linux/ConvUtils.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#ifndef __CONV_UTILS__H__
|
||||
#define __CONV_UTILS__H__
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
#include "PlatformDefs.h" // UINT DWORD LPCSTR LPSTR LPBOOL ...
|
||||
|
||||
int WideCharToMultiByte(
|
||||
UINT CodePage,
|
||||
DWORD dwFlags,
|
||||
LPCWSTR lpWideCharStr,
|
||||
int cchWideChar,
|
||||
LPSTR lpMultiByteStr,
|
||||
int cbMultiByte,
|
||||
LPCSTR lpDefaultChar,
|
||||
LPBOOL lpUsedDefaultChar
|
||||
);
|
||||
|
||||
int MultiByteToWideChar(
|
||||
UINT CodePage,
|
||||
DWORD dwFlags,
|
||||
LPCSTR lpMultiByteStr,
|
||||
int cbMultiByte,
|
||||
LPWSTR lpWideCharStr,
|
||||
int cchWideChar
|
||||
);
|
||||
|
||||
|
||||
DWORD GetLastError();
|
||||
VOID SetLastError(DWORD dwErrCode);
|
||||
|
||||
#endif
|
||||
678
linux/PlatformDefs.h
Normal file
678
linux/PlatformDefs.h
Normal file
|
|
@ -0,0 +1,678 @@
|
|||
#ifndef __PLATFORM_DEFS_H__
|
||||
#define __PLATFORM_DEFS_H__
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef _LINUX
|
||||
|
||||
#define LINE_ENDING "\n"
|
||||
|
||||
#ifndef _LARGEFILE64_SOURCE
|
||||
#define _LARGEFILE64_SOURCE
|
||||
#endif
|
||||
|
||||
#undef _FILE_OFFSET_BITS
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#ifdef __APPLE__
|
||||
#include <stdio.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <mach/mach.h>
|
||||
#else
|
||||
#include <sys/sysinfo.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
// do not move this, it will break osx build bad"
|
||||
#ifdef HAS_SDL
|
||||
#include <SDL/SDL.h>
|
||||
#endif
|
||||
|
||||
#if defined(__ppc__) || defined(__powerpc__)
|
||||
#define PIXEL_ASHIFT 0
|
||||
#define PIXEL_RSHIFT 8
|
||||
#define PIXEL_GSHIFT 16
|
||||
#define PIXEL_BSHIFT 24
|
||||
#define AMASK 0x000000ff
|
||||
#define RMASK 0x0000ff00
|
||||
#define GMASK 0x00ff0000
|
||||
#define BMASK 0xff000000
|
||||
#else
|
||||
#define PIXEL_ASHIFT 24
|
||||
#define PIXEL_RSHIFT 16
|
||||
#define PIXEL_GSHIFT 8
|
||||
#define PIXEL_BSHIFT 0
|
||||
#define AMASK 0xff000000
|
||||
#define RMASK 0x00ff0000
|
||||
#define GMASK 0x0000ff00
|
||||
#define BMASK 0x000000ff
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef PRId64
|
||||
#ifdef _MSC_VER
|
||||
#define PRId64 "I64d"
|
||||
#else
|
||||
#if __WORDSIZE == 64
|
||||
#define PRId64 "ld"
|
||||
#else
|
||||
#define PRId64 "lld"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef PRIu64
|
||||
#ifdef _MSC_VER
|
||||
#define PRIu64 "I64u"
|
||||
#else
|
||||
#if __WORDSIZE == 64
|
||||
#define PRIu64 "lu"
|
||||
#else
|
||||
#define PRIu64 "llu"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef PRIx64
|
||||
#ifdef _MSC_VER
|
||||
#define PRIx64 "I64x"
|
||||
#else
|
||||
#if __WORDSIZE == 64
|
||||
#define PRIx64 "lx"
|
||||
#else
|
||||
#define PRIx64 "llx"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef PRIdS
|
||||
#define PRIdS "zd"
|
||||
#endif
|
||||
|
||||
#ifndef PRIuS
|
||||
#define PRIuS "zu"
|
||||
#endif
|
||||
|
||||
#ifdef _LINUX
|
||||
|
||||
#define XXLog(a,b) printf("%s", (b))
|
||||
|
||||
#ifndef INSTALL_PATH
|
||||
#define INSTALL_PATH "/usr/share/xbmc"
|
||||
#endif
|
||||
|
||||
#ifndef BIN_INSTALL_PATH
|
||||
#define BIN_INSTALL_PATH "/usr/lib/xbmc"
|
||||
#endif
|
||||
|
||||
#define CONST const
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
#define _fdopen fdopen
|
||||
#define _vsnprintf vsnprintf
|
||||
#define _stricmp strcasecmp
|
||||
#define stricmp strcasecmp
|
||||
#define strcmpi strcasecmp
|
||||
#define strnicmp strncasecmp
|
||||
#define _atoi64(x) atoll(x)
|
||||
#define CopyMemory(dst,src,size) memmove(dst, src, size)
|
||||
#define ZeroMemory(dst,size) memset(dst, 0, size)
|
||||
|
||||
#define VOID void
|
||||
#define byte unsigned char
|
||||
#define __int8 char
|
||||
#define __int16 short
|
||||
#define __int32 int
|
||||
#define __int64 long long
|
||||
#define __uint64 unsigned long long
|
||||
|
||||
#if defined(__x86_64__) || defined(__powerpc__) || defined(__ppc__) || defined (__arm__) // should this be powerpc64 only?
|
||||
#define __stdcall
|
||||
#else /* !__x86_64__ */
|
||||
#define __stdcall __attribute__((__stdcall__))
|
||||
#endif /* __x86_64__ */
|
||||
#define __cdecl
|
||||
#define WINBASEAPI
|
||||
#define NTAPI __stdcall
|
||||
#define CALLBACK __stdcall
|
||||
#define WINAPI __stdcall
|
||||
#define WINAPIV __cdecl
|
||||
#ifndef __APPLE__
|
||||
#define APIENTRY WINAPI
|
||||
#else
|
||||
#define APIENTRY
|
||||
#endif
|
||||
#define APIPRIVATE __stdcall
|
||||
#define IN
|
||||
#define OUT
|
||||
#define OPTIONAL
|
||||
#define _declspec(X)
|
||||
#define __declspec(X)
|
||||
|
||||
#define __try try
|
||||
#define EXCEPTION_EXECUTE_HANDLER ...
|
||||
//NOTE: dont try to define __except because it breaks g++ (already uses it).
|
||||
|
||||
typedef pthread_t ThreadIdentifier;
|
||||
|
||||
struct CXHandle; // forward declaration
|
||||
typedef CXHandle* HANDLE;
|
||||
|
||||
typedef void* HINSTANCE;
|
||||
typedef void* HMODULE;
|
||||
|
||||
typedef unsigned int DWORD;
|
||||
typedef unsigned short WORD;
|
||||
typedef unsigned char BYTE;
|
||||
typedef char CHAR;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef wchar_t WCHAR;
|
||||
typedef int BOOL;
|
||||
typedef BYTE BOOLEAN;
|
||||
typedef short SHORT;
|
||||
typedef unsigned short USHORT;
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
// typedef int INT32; // unused; must match Xmd.h but why bother
|
||||
typedef unsigned int UINT32;
|
||||
typedef long long INT64;
|
||||
typedef unsigned long long UINT64;
|
||||
typedef long LONG;
|
||||
typedef long long LONGLONG;
|
||||
typedef unsigned long ULONG;
|
||||
typedef float FLOAT;
|
||||
typedef size_t SIZE_T;
|
||||
typedef void* PVOID;
|
||||
typedef void* LPVOID;
|
||||
//typedef PVOID HANDLE;
|
||||
#define INVALID_HANDLE_VALUE ((HANDLE)~0U)
|
||||
typedef HANDLE HDC;
|
||||
typedef void* HWND;
|
||||
typedef LONG HRESULT;
|
||||
typedef BYTE* LPBYTE;
|
||||
typedef DWORD* LPDWORD;
|
||||
typedef CONST CHAR* LPCSTR;
|
||||
typedef CONST WCHAR* LPCWSTR;
|
||||
typedef CHAR* LPTSTR;
|
||||
typedef WCHAR *PWSTR, *LPWSTR, *NWPSTR;
|
||||
typedef CHAR *PSTR, *LPSTR, *NPSTR;
|
||||
typedef LONG *PLONG, *LPLONG;
|
||||
#ifdef UNICODE
|
||||
typedef LPCWSTR LPCTSTR;
|
||||
#else
|
||||
typedef LPCSTR LPCTSTR;
|
||||
#endif
|
||||
typedef unsigned __int64 ULONGLONG;
|
||||
typedef long LONG_PTR;
|
||||
typedef unsigned long ULONG_PTR;
|
||||
typedef ULONG_PTR DWORD_PTR;
|
||||
typedef __int64 __time64_t;
|
||||
typedef intptr_t (*FARPROC)(void);
|
||||
|
||||
#define MAXWORD 0xffff
|
||||
#define MAXDWORD 0xffffffff
|
||||
|
||||
typedef DWORD LCID;
|
||||
typedef WORD* LPWORD;
|
||||
typedef BOOL* LPBOOL;
|
||||
typedef CHAR* LPCHAR;
|
||||
typedef CHAR* PCHAR;
|
||||
typedef const void* LPCVOID;
|
||||
|
||||
typedef union _LARGE_INTEGER
|
||||
{
|
||||
struct {
|
||||
DWORD LowPart;
|
||||
int32_t HighPart;
|
||||
} u;
|
||||
LONGLONG QuadPart;
|
||||
} LARGE_INTEGER, *PLARGE_INTEGER;
|
||||
|
||||
typedef union _ULARGE_INTEGER {
|
||||
struct {
|
||||
DWORD LowPart;
|
||||
DWORD HighPart;
|
||||
} u;
|
||||
ULONGLONG QuadPart;
|
||||
} ULARGE_INTEGER, *PULARGE_INTEGER;
|
||||
|
||||
#define MAKELONG(low,high) ((LONG)(((WORD)((DWORD_PTR)(low) & 0xFFFF)) | ((DWORD)((WORD)((DWORD_PTR)(high) & 0xFFFF))) << 16))
|
||||
LONGLONG Int32x32To64(LONG Multiplier, LONG Multiplicand);
|
||||
|
||||
void OutputDebugString(LPCTSTR lpOuputString);
|
||||
|
||||
// Date / Time
|
||||
|
||||
typedef struct _SYSTEMTIME
|
||||
{
|
||||
WORD wYear;
|
||||
WORD wMonth;
|
||||
WORD wDayOfWeek;
|
||||
WORD wDay;
|
||||
WORD wHour;
|
||||
WORD wMinute;
|
||||
WORD wSecond;
|
||||
WORD wMilliseconds;
|
||||
} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;
|
||||
|
||||
typedef struct _TIME_ZONE_INFORMATION {
|
||||
LONG Bias;
|
||||
WCHAR StandardName[32];
|
||||
SYSTEMTIME StandardDate;
|
||||
LONG StandardBias;
|
||||
WCHAR DaylightName[32];
|
||||
SYSTEMTIME DaylightDate;
|
||||
LONG DaylightBias;
|
||||
} TIME_ZONE_INFORMATION, *PTIME_ZONE_INFORMATION, *LPTIME_ZONE_INFORMATION;
|
||||
|
||||
#define TIME_ZONE_ID_INVALID ((DWORD)0xFFFFFFFF)
|
||||
#define TIME_ZONE_ID_UNKNOWN 0
|
||||
#define TIME_ZONE_ID_STANDARD 1
|
||||
#define TIME_ZONE_ID_DAYLIGHT 2
|
||||
|
||||
// Thread
|
||||
#define THREAD_BASE_PRIORITY_LOWRT 15
|
||||
#define THREAD_BASE_PRIORITY_MAX 2
|
||||
#define THREAD_BASE_PRIORITY_MIN -2
|
||||
#define THREAD_BASE_PRIORITY_IDLE -15
|
||||
#define THREAD_PRIORITY_LOWEST THREAD_BASE_PRIORITY_MIN
|
||||
#define THREAD_PRIORITY_BELOW_NORMAL (THREAD_PRIORITY_LOWEST+1)
|
||||
#define THREAD_PRIORITY_NORMAL 0
|
||||
#define THREAD_PRIORITY_HIGHEST THREAD_BASE_PRIORITY_MAX
|
||||
#define THREAD_PRIORITY_ABOVE_NORMAL (THREAD_PRIORITY_HIGHEST-1)
|
||||
#define THREAD_PRIORITY_ERROR_RETURN (0x7fffffff)
|
||||
#define THREAD_PRIORITY_TIME_CRITICAL THREAD_BASE_PRIORITY_LOWRT
|
||||
#define THREAD_PRIORITY_IDLE THREAD_BASE_PRIORITY_IDLE
|
||||
|
||||
// Network
|
||||
#define SOCKADDR_IN struct sockaddr_in
|
||||
#define IN_ADDR struct in_addr
|
||||
#define SOCKET_ERROR (-1)
|
||||
#define INVALID_SOCKET (~0)
|
||||
#define closesocket(s) close(s)
|
||||
#define ioctlsocket(s, f, v) ioctl(s, f, v)
|
||||
#define WSAGetLastError() (errno)
|
||||
#define WSASetLastError(e) (errno = e)
|
||||
#define WSAECONNRESET ECONNRESET
|
||||
#define WSAHOST_NOT_FOUND ENOENT
|
||||
#define WSAETIMEDOUT ETIMEDOUT
|
||||
#define WSAEADDRINUSE EADDRINUSE
|
||||
#define WSAECANCELLED EINTR
|
||||
#define WSAECONNREFUSED ECONNREFUSED
|
||||
#define WSAECONNABORTED ECONNABORTED
|
||||
#define WSAETIMEDOUT ETIMEDOUT
|
||||
|
||||
typedef int SOCKET;
|
||||
|
||||
// Thread
|
||||
typedef int (*LPTHREAD_START_ROUTINE)(void *);
|
||||
|
||||
// File
|
||||
#define O_BINARY 0
|
||||
#define O_TEXT 0
|
||||
#define _O_TRUNC O_TRUNC
|
||||
#define _O_RDONLY O_RDONLY
|
||||
#define _O_WRONLY O_WRONLY
|
||||
#define _off_t off_t
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <sched.h>
|
||||
#include <AvailabilityMacros.h>
|
||||
typedef int64_t off64_t;
|
||||
typedef off_t __off_t;
|
||||
typedef off64_t __off64_t;
|
||||
typedef fpos_t fpos64_t;
|
||||
#if (MAC_OS_X_VERSION_MAX_ALLOWED < 1050)
|
||||
#define __stat64 stat
|
||||
#define stat64 stat
|
||||
#define statfs64 statfs
|
||||
#define fstat64 fstat
|
||||
#elif defined(__arm__)
|
||||
#define __stat64 stat
|
||||
#define stat64 stat
|
||||
#define statfs64 statfs
|
||||
#define fstat64 fstat
|
||||
#else
|
||||
#define fstat64 fstat
|
||||
#endif
|
||||
#else
|
||||
#define __stat64 stat64
|
||||
#endif
|
||||
|
||||
struct _stati64 {
|
||||
dev_t st_dev;
|
||||
ino_t st_ino;
|
||||
unsigned short st_mode;
|
||||
short st_nlink;
|
||||
short st_uid;
|
||||
short st_gid;
|
||||
dev_t st_rdev;
|
||||
__int64 st_size;
|
||||
time_t _st_atime;
|
||||
time_t _st_mtime;
|
||||
time_t _st_ctime;
|
||||
};
|
||||
|
||||
typedef struct _FILETIME
|
||||
{
|
||||
DWORD dwLowDateTime;
|
||||
DWORD dwHighDateTime;
|
||||
} FILETIME, *PFILETIME, *LPFILETIME;
|
||||
|
||||
typedef struct _WIN32_FIND_DATA
|
||||
{
|
||||
DWORD dwFileAttributes;
|
||||
FILETIME ftCreationTime;
|
||||
FILETIME ftLastAccessTime;
|
||||
FILETIME ftLastWriteTime;
|
||||
DWORD nFileSizeHigh;
|
||||
DWORD nFileSizeLow;
|
||||
DWORD dwReserved0;
|
||||
DWORD dwReserved1;
|
||||
CHAR cFileName[260];
|
||||
CHAR cAlternateFileName[14];
|
||||
} WIN32_FIND_DATA, *PWIN32_FIND_DATA, *LPWIN32_FIND_DATA;
|
||||
|
||||
#define LPWIN32_FIND_DATAA LPWIN32_FIND_DATA
|
||||
|
||||
#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
|
||||
|
||||
typedef struct _SECURITY_ATTRIBUTES {
|
||||
DWORD nLength;
|
||||
LPVOID lpSecurityDescriptor;
|
||||
BOOL bInheritHandle;
|
||||
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
|
||||
|
||||
#define FILE_BEGIN 0
|
||||
#define FILE_CURRENT 1
|
||||
#define FILE_END 2
|
||||
|
||||
#define _S_IFREG S_IFREG
|
||||
#define _S_IFDIR S_IFDIR
|
||||
#define MAX_PATH PATH_MAX
|
||||
|
||||
#define _stat stat
|
||||
|
||||
// Memory
|
||||
typedef struct _MEMORYSTATUS
|
||||
{
|
||||
DWORD dwLength;
|
||||
DWORD dwMemoryLoad;
|
||||
|
||||
uint64_t dwTotalPhys;
|
||||
uint64_t dwAvailPhys;
|
||||
uint64_t dwTotalPageFile;
|
||||
uint64_t dwAvailPageFile;
|
||||
uint64_t dwTotalVirtual;
|
||||
uint64_t dwAvailVirtual;
|
||||
} MEMORYSTATUS, *LPMEMORYSTATUS;
|
||||
|
||||
// Common HRESULT values
|
||||
#ifndef NOERROR
|
||||
#define NOERROR (0L)
|
||||
#endif
|
||||
#ifndef S_OK
|
||||
#define S_OK (0L)
|
||||
#endif
|
||||
#ifndef E_FAIL
|
||||
#define E_FAIL (0x80004005L)
|
||||
#endif
|
||||
#ifndef E_OUTOFMEMORY
|
||||
#define E_OUTOFMEMORY (0x8007000EL)
|
||||
#endif
|
||||
#define FAILED(Status) ((HRESULT)(Status)<0)
|
||||
|
||||
// Basic D3D stuff
|
||||
typedef struct _RECT {
|
||||
LONG left;
|
||||
LONG top;
|
||||
LONG right;
|
||||
LONG bottom;
|
||||
} RECT, *PRECT;
|
||||
|
||||
typedef DWORD D3DCOLOR;
|
||||
|
||||
typedef enum _D3DFORMAT
|
||||
{
|
||||
D3DFMT_A8R8G8B8 = 0x00000006,
|
||||
D3DFMT_DXT1 = 0x0000000C,
|
||||
D3DFMT_DXT2 = 0x0000000E,
|
||||
D3DFMT_DXT4 = 0x0000000F,
|
||||
D3DFMT_UNKNOWN = 0xFFFFFFFF
|
||||
} D3DFORMAT;
|
||||
|
||||
typedef enum D3DRESOURCETYPE
|
||||
{
|
||||
D3DRTYPE_SURFACE = 1,
|
||||
D3DRTYPE_VOLUME = 2,
|
||||
D3DRTYPE_TEXTURE = 3,
|
||||
D3DRTYPE_VOLUMETEXTURE = 4,
|
||||
D3DRTYPE_CubeTexture = 5,
|
||||
D3DRTYPE_VERTEXBUFFER = 6,
|
||||
D3DRTYPE_INDEXBUFFER = 7,
|
||||
D3DRTYPE_FORCE_DWORD = 0x7fffffff
|
||||
} D3DRESOURCETYPE, *LPD3DRESOURCETYPE;
|
||||
|
||||
typedef enum D3DXIMAGE_FILEFORMAT
|
||||
{
|
||||
D3DXIFF_BMP = 0,
|
||||
D3DXIFF_JPG = 1,
|
||||
D3DXIFF_TGA = 2,
|
||||
D3DXIFF_PNG = 3,
|
||||
D3DXIFF_DDS = 4,
|
||||
D3DXIFF_PPM = 5,
|
||||
D3DXIFF_DIB = 6,
|
||||
D3DXIFF_HDR = 7,
|
||||
D3DXIFF_PFM = 8,
|
||||
D3DXIFF_FORCE_DWORD = 0x7fffffff
|
||||
} D3DXIMAGE_FILEFORMAT, *LPD3DXIMAGE_FILEFORMAT;
|
||||
|
||||
typedef struct D3DXIMAGE_INFO {
|
||||
UINT Width;
|
||||
UINT Height;
|
||||
UINT Depth;
|
||||
UINT MipLevels;
|
||||
D3DFORMAT Format;
|
||||
D3DRESOURCETYPE ResourceType;
|
||||
D3DXIMAGE_FILEFORMAT ImageFileFormat;
|
||||
} D3DXIMAGE_INFO, *LPD3DXIMAGE_INFO;
|
||||
|
||||
typedef struct _D3DPRESENT_PARAMETERS_
|
||||
{
|
||||
UINT BackBufferWidth;
|
||||
UINT BackBufferHeight;
|
||||
D3DFORMAT BackBufferFormat;
|
||||
UINT BackBufferCount;
|
||||
//D3DMULTISAMPLE_TYPE MultiSampleType;
|
||||
//D3DSWAPEFFECT SwapEffect;
|
||||
//HWND hDeviceWindow;
|
||||
BOOL Windowed;
|
||||
BOOL EnableAutoDepthStencil;
|
||||
D3DFORMAT AutoDepthStencilFormat;
|
||||
DWORD Flags;
|
||||
UINT FullScreen_RefreshRateInHz;
|
||||
UINT FullScreen_PresentationInterval;
|
||||
//D3DSurface *BufferSurfaces[3];
|
||||
//D3DSurface *DepthStencilSurface;
|
||||
} D3DPRESENT_PARAMETERS;
|
||||
|
||||
typedef enum D3DPRIMITIVETYPE
|
||||
{
|
||||
D3DPT_POINTLIST = 1,
|
||||
D3DPT_LINELIST = 2,
|
||||
D3DPT_LINESTRIP = 3,
|
||||
D3DPT_TRIANGLELIST = 4,
|
||||
D3DPT_TRIANGLESTRIP = 5,
|
||||
D3DPT_TRIANGLEFAN = 6,
|
||||
D3DPT_FORCE_DWORD = 0x7fffffff
|
||||
} D3DPRIMITIVETYPE, *LPD3DPRIMITIVETYPE;
|
||||
|
||||
typedef struct _D3DMATRIX {
|
||||
union {
|
||||
struct {
|
||||
float _11, _12, _13, _14;
|
||||
float _21, _22, _23, _24;
|
||||
float _31, _32, _33, _34;
|
||||
float _41, _42, _43, _44;
|
||||
} u;
|
||||
float m[4][4];
|
||||
};
|
||||
} D3DMATRIX;
|
||||
|
||||
// Misc stuff found in the code, not really important
|
||||
#define PAGE_READONLY 0x02
|
||||
#define PAGE_READWRITE 0x04
|
||||
#define MAXULONG_PTR ((ULONG) 0xffffffff)
|
||||
|
||||
// CreateFile defines
|
||||
#define FILE_FLAG_WRITE_THROUGH 0x80000000
|
||||
#define FILE_FLAG_OVERLAPPED 0x40000000
|
||||
#define FILE_FLAG_NO_BUFFERING 0x20000000
|
||||
#define FILE_FLAG_RANDOM_ACCESS 0x10000000
|
||||
#define FILE_FLAG_SEQUENTIAL_SCAN 0x08000000
|
||||
#define FILE_FLAG_DELETE_ON_CLOSE 0x04000000
|
||||
#define FILE_FLAG_BACKUP_SEMANTICS 0x02000000
|
||||
#define FILE_FLAG_POSIX_SEMANTICS 0x01000000
|
||||
#define FILE_FLAG_OPEN_REPARSE_POINT 0x00200000
|
||||
#define FILE_FLAG_OPEN_NO_RECALL 0x00100000
|
||||
#define FILE_FLAG_FIRST_PIPE_INSTANCE 0x00080000
|
||||
|
||||
#define CREATE_NEW 1
|
||||
#define CREATE_ALWAYS 2
|
||||
#define OPEN_EXISTING 3
|
||||
#define OPEN_ALWAYS 4
|
||||
#define TRUNCATE_EXISTING 5
|
||||
|
||||
#define FILE_ATTRIBUTE_NORMAL 0x00000080
|
||||
#define FILE_ATTRIBUTE_READONLY 0x00000001
|
||||
#define FILE_ATTRIBUTE_HIDDEN 0x00000002
|
||||
#define FILE_ATTRIBUTE_SYSTEM 0x00000004
|
||||
#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
|
||||
|
||||
#define FILE_READ_DATA ( 0x0001 )
|
||||
#define FILE_WRITE_DATA ( 0x0002 )
|
||||
#define FILE_APPEND_DATA ( 0x0004 )
|
||||
|
||||
#define GENERIC_READ FILE_READ_DATA
|
||||
#define GENERIC_WRITE FILE_WRITE_DATA
|
||||
#define FILE_SHARE_READ 0x00000001
|
||||
#define FILE_SHARE_WRITE 0x00000002
|
||||
#define FILE_SHARE_DELETE 0x00000004
|
||||
|
||||
|
||||
// String
|
||||
char *itoa(int i, char *a, int r);
|
||||
void strlwr(char* string);
|
||||
void strupr(char* string);
|
||||
|
||||
// Audio stuff
|
||||
typedef struct tWAVEFORMATEX
|
||||
{
|
||||
WORD wFormatTag;
|
||||
WORD nChannels;
|
||||
DWORD nSamplesPerSec;
|
||||
DWORD nAvgBytesPerSec;
|
||||
WORD nBlockAlign;
|
||||
WORD wBitsPerSample;
|
||||
WORD cbSize;
|
||||
} __attribute__((__packed__)) WAVEFORMATEX, *PWAVEFORMATEX, *LPWAVEFORMATEX;
|
||||
|
||||
#define WAVE_FORMAT_UNKNOWN 0x0000
|
||||
#define WAVE_FORMAT_PCM 0x0001
|
||||
#define WAVE_FORMAT_ADPCM 0x0002
|
||||
#define WAVE_FORMAT_IEEE_FLOAT 0x0003
|
||||
#define WAVE_FORMAT_EXTENSIBLE 0xFFFE
|
||||
|
||||
#define SPEAKER_FRONT_LEFT 0x00001
|
||||
#define SPEAKER_FRONT_RIGHT 0x00002
|
||||
#define SPEAKER_FRONT_CENTER 0x00004
|
||||
#define SPEAKER_LOW_FREQUENCY 0x00008
|
||||
#define SPEAKER_BACK_LEFT 0x00010
|
||||
#define SPEAKER_BACK_RIGHT 0x00020
|
||||
#define SPEAKER_FRONT_LEFT_OF_CENTER 0x00040
|
||||
#define SPEAKER_FRONT_RIGHT_OF_CENTER 0x00080
|
||||
#define SPEAKER_BACK_CENTER 0x00100
|
||||
#define SPEAKER_SIDE_LEFT 0x00200
|
||||
#define SPEAKER_SIDE_RIGHT 0x00400
|
||||
#define SPEAKER_TOP_CENTER 0x00800
|
||||
#define SPEAKER_TOP_FRONT_LEFT 0x01000
|
||||
#define SPEAKER_TOP_FRONT_CENTER 0x02000
|
||||
#define SPEAKER_TOP_FRONT_RIGHT 0x04000
|
||||
#define SPEAKER_TOP_BACK_LEFT 0x08000
|
||||
#define SPEAKER_TOP_BACK_CENTER 0x10000
|
||||
#define SPEAKER_TOP_BACK_RIGHT 0x20000
|
||||
|
||||
typedef struct tGUID
|
||||
{
|
||||
DWORD Data1;
|
||||
WORD Data2, Data3;
|
||||
BYTE Data4[8];
|
||||
} __attribute__((__packed__)) GUID;
|
||||
|
||||
static const GUID KSDATAFORMAT_SUBTYPE_UNKNOWN = {
|
||||
WAVE_FORMAT_UNKNOWN,
|
||||
0x0000, 0x0000,
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||||
};
|
||||
|
||||
static const GUID KSDATAFORMAT_SUBTYPE_PCM = {
|
||||
WAVE_FORMAT_PCM,
|
||||
0x0000, 0x0010,
|
||||
{0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
|
||||
};
|
||||
|
||||
static const GUID KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {
|
||||
WAVE_FORMAT_IEEE_FLOAT,
|
||||
0x0000, 0x0010,
|
||||
{0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
|
||||
};
|
||||
|
||||
typedef struct tWAVEFORMATEXTENSIBLE
|
||||
{
|
||||
WAVEFORMATEX Format;
|
||||
union
|
||||
{
|
||||
WORD wValidBitsPerSample;
|
||||
WORD wSamplesPerBlock;
|
||||
WORD wReserved;
|
||||
} Samples;
|
||||
DWORD dwChannelMask;
|
||||
GUID SubFormat;
|
||||
} __attribute__((__packed__)) WAVEFORMATEXTENSIBLE;
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif //__PLATFORM_DEFS_H__
|
||||
|
||||
|
||||
36
linux/PlatformInclude.h
Normal file
36
linux/PlatformInclude.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#ifndef __PLATFORM_INCLUDE__H__
|
||||
#define __PLATFORM_INCLUDE__H__
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "PlatformDefs.h"
|
||||
#include "XHandlePublic.h"
|
||||
#include "XFileUtils.h"
|
||||
#include "XSyncUtils.h"
|
||||
#include "XEventUtils.h"
|
||||
#include "XTimeUtils.h"
|
||||
#include "XThreadUtils.h"
|
||||
#include "XMemUtils.h"
|
||||
#include "ConvUtils.h"
|
||||
|
||||
#endif
|
||||
|
||||
58
linux/RBP.cpp
Normal file
58
linux/RBP.cpp
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2009 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "RBP.h"
|
||||
#include "utils/log.h"
|
||||
|
||||
#define CLASSNAME "CRBP"
|
||||
|
||||
CRBP::CRBP()
|
||||
{
|
||||
m_initialized = false;
|
||||
m_DllBcmHost = new DllBcmHost();
|
||||
}
|
||||
|
||||
CRBP::~CRBP()
|
||||
{
|
||||
Deinitialize();
|
||||
delete m_DllBcmHost;
|
||||
}
|
||||
|
||||
bool CRBP::Initialize()
|
||||
{
|
||||
m_initialized = m_DllBcmHost->Load();
|
||||
if(!m_initialized)
|
||||
return false;
|
||||
|
||||
m_DllBcmHost->bcm_host_init();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CRBP::Deinitialize()
|
||||
{
|
||||
m_DllBcmHost->bcm_host_deinit();
|
||||
|
||||
if(m_initialized)
|
||||
m_DllBcmHost->Unload();
|
||||
|
||||
m_initialized = false;
|
||||
}
|
||||
61
linux/RBP.h
Normal file
61
linux/RBP.h
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
#pragma once
|
||||
/*
|
||||
* Copyright (C) 2005-2009 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
#define _HAVE_SBRK 1
|
||||
#define HAVE_CMAKE_CONFIG 1
|
||||
#define _REENTRANT 1
|
||||
#ifndef VCHI_BULK_ALIGN
|
||||
#define VCHI_BULK_ALIGN 1
|
||||
#endif
|
||||
#ifndef VCHI_BULK_GRANULARITY
|
||||
#define VCHI_BULK_GRANULARITY 1
|
||||
#endif
|
||||
*/
|
||||
//#define OMX_SKIP64BIT
|
||||
#ifndef USE_VCHIQ_ARM
|
||||
#define USE_VCHIQ_ARM
|
||||
#endif
|
||||
#ifndef __VIDEOCORE4__
|
||||
#define __VIDEOCORE4__
|
||||
#endif
|
||||
#ifndef HAVE_VMCS_CONFIG
|
||||
#define HAVE_VMCS_CONFIG
|
||||
#endif
|
||||
|
||||
#include "DllBCM.h"
|
||||
|
||||
class CRBP
|
||||
{
|
||||
public:
|
||||
CRBP();
|
||||
~CRBP();
|
||||
|
||||
bool Initialize();
|
||||
void Deinitialize();
|
||||
|
||||
private:
|
||||
DllBcmHost *m_DllBcmHost;
|
||||
bool m_initialized;
|
||||
};
|
||||
|
||||
extern CRBP g_RBP;
|
||||
52
linux/XMemUtils.cpp
Normal file
52
linux/XMemUtils.cpp
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "XMemUtils.h"
|
||||
|
||||
#undef ALIGN
|
||||
#define ALIGN(value, alignment) (((value)+(alignment-1))&~(alignment-1))
|
||||
|
||||
// aligned memory allocation.
|
||||
// in order to do so - we alloc extra space and store the original allocation in it (so that we can free later on).
|
||||
// the returned address will be the nearest alligned address within the space allocated.
|
||||
void *_aligned_malloc(size_t s, size_t alignTo) {
|
||||
|
||||
char *pFull = (char*)malloc(s + alignTo + sizeof(char *));
|
||||
char *pAlligned = (char *)ALIGN(((unsigned long)pFull + sizeof(char *)), alignTo);
|
||||
|
||||
*(char **)(pAlligned - sizeof(char*)) = pFull;
|
||||
|
||||
return(pAlligned);
|
||||
}
|
||||
|
||||
void _aligned_free(void *p) {
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
char *pFull = *(char **)(((char *)p) - sizeof(char *));
|
||||
free(pFull);
|
||||
}
|
||||
|
||||
|
||||
37
linux/XMemUtils.d
Normal file
37
linux/XMemUtils.d
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
linux/XMemUtils.o: linux/XMemUtils.cpp \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/stdlib.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/features.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/sys/cdefs.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/bits/wordsize.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/gnu/stubs.h \
|
||||
/usr/local/bcm-gcc/bin/../lib/gcc/arm-bcm2708-linux-gnueabi/4.5.1/include/stddef.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/bits/waitflags.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/bits/waitstatus.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/endian.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/bits/endian.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/bits/byteswap.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/xlocale.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/sys/types.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/bits/types.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/bits/typesizes.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/time.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/sys/select.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/bits/select.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/bits/sigset.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/bits/time.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/sys/sysmacros.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/bits/pthreadtypes.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/alloca.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/stdio.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/libio.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/_G_config.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/wchar.h \
|
||||
/usr/local/bcm-gcc/bin/../lib/gcc/arm-bcm2708-linux-gnueabi/4.5.1/include/stdarg.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/bits/stdio_lim.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/bits/sys_errlist.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/unistd.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/bits/posix_opt.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/bits/environments.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/bits/confname.h \
|
||||
/usr/local/bcm-gcc/bin/../arm-bcm2708-linux-gnueabi//sys-root/usr/include/getopt.h \
|
||||
linux/XMemUtils.h
|
||||
31
linux/XMemUtils.h
Normal file
31
linux/XMemUtils.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef __XMEMUTILS__H__
|
||||
#define __XMEMUTILS__H__
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
// aligned memory allocation and free. memory returned will be aligned to "alignTo" bytes.
|
||||
// this is a linux (actually platfom free) implementation of the win32 CRT methods _aligned_malloc and _aligned_free.
|
||||
void *_aligned_malloc(size_t s, size_t alignTo);
|
||||
void _aligned_free(void *p) ;
|
||||
|
||||
#endif
|
||||
|
||||
44
linux/XSyncUtils.h
Normal file
44
linux/XSyncUtils.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
#ifndef __X_SYNC_UTILS_
|
||||
#define __X_SYNC_UTILS_
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "PlatformDefs.h"
|
||||
#include "XHandlePublic.h"
|
||||
|
||||
#ifdef _LINUX
|
||||
|
||||
#define STATUS_WAIT_0 ((DWORD )0x00000000L)
|
||||
#define WAIT_FAILED ((DWORD)0xFFFFFFFF)
|
||||
#define WAIT_OBJECT_0 ((STATUS_WAIT_0 ) + 0 )
|
||||
#define WAIT_TIMEOUT 258L
|
||||
#define INFINITE 0xFFFFFFFF
|
||||
#define STATUS_ABANDONED_WAIT_0 0x00000080
|
||||
#define WAIT_ABANDONED ((STATUS_ABANDONED_WAIT_0 ) + 0 )
|
||||
#define WAIT_ABANDONED_0 ((STATUS_ABANDONED_WAIT_0 ) + 0 )
|
||||
|
||||
void GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
28
linux/stat_utf8.h
Normal file
28
linux/stat_utf8.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2011 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef STAT_UTF8_H__
|
||||
#define STAT_UTF8_H__
|
||||
|
||||
#define stat64_utf8 stat64
|
||||
|
||||
#endif //STAT_UTF8_H__
|
||||
|
||||
32
linux/stdio_utf8.h
Normal file
32
linux/stdio_utf8.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2011 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef STDIO_UTF8_H__
|
||||
#define STDIO_UTF8_H__
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#define remove_utf8 remove
|
||||
#define rename_utf8 rename
|
||||
#define fopen64_utf8 fopen
|
||||
|
||||
#endif // STDIO_UTF8_H__
|
||||
|
||||
34
omxplayer
Executable file
34
omxplayer
Executable file
|
|
@ -0,0 +1,34 @@
|
|||
#!/bin/sh
|
||||
|
||||
#mount -t nfs -o rsize=32768,wsize=32768,intr 192.168.10.1:/data/video /media
|
||||
|
||||
OMXPLAYER="./omxplayer.bin"
|
||||
FBSET="/usr/sbin/fbset"
|
||||
|
||||
if [ -e /usr/bin/omxplayer.bin ]; then
|
||||
OMXPLAYER="/usr/bin/omxplayer.bin"
|
||||
fi
|
||||
|
||||
if [ -e /usr/lib/omxplayer ]; then
|
||||
export LD_LIBRARY_PATH=/opt/vc/lib:/usr/lib/omxplayer:$LD_LIBRARY_PATH
|
||||
else
|
||||
export LD_LIBRARY_PATH=$PWD/ffmpeg_compiled/usr/local/lib:/opt/vc/lib:$LD_LIBRARY_PATH
|
||||
fi
|
||||
|
||||
XRES=1920
|
||||
YRES=1080
|
||||
|
||||
XRES=1600
|
||||
YRES=900
|
||||
|
||||
if [ -e $FBSET ]; then
|
||||
echo 0 > /sys/class/vtconsole/vtcon1/bind
|
||||
fbset -xres 1 -yres 1
|
||||
fi
|
||||
|
||||
./omxplayer.bin "$@"
|
||||
|
||||
if [ -e $FBSET ]; then
|
||||
fbset -xres ${XRES} -yres ${YRES}
|
||||
echo 1 > /sys/class/vtconsole/vtcon1/bind
|
||||
fi
|
||||
730
omxplayer.cpp
Normal file
730
omxplayer.cpp
Normal file
|
|
@ -0,0 +1,730 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (C) 2012 Edgar Hucek
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <termios.h>
|
||||
#include <sys/mman.h>
|
||||
#include <linux/fb.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#define AV_NOWARN_DEPRECATED
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/avutil.h>
|
||||
};
|
||||
|
||||
#include "OMXStreamInfo.h"
|
||||
|
||||
#include "utils/log.h"
|
||||
|
||||
#include "DllAvUtil.h"
|
||||
#include "DllAvFormat.h"
|
||||
#include "DllAvFilter.h"
|
||||
#include "DllAvCodec.h"
|
||||
#include "DllAvCore.h"
|
||||
#include "linux/RBP.h"
|
||||
|
||||
#include "OMXVideo.h"
|
||||
#include "OMXAudioCodecOMX.h"
|
||||
#include "utils/PCMRemap.h"
|
||||
#include "OMXClock.h"
|
||||
#include "OMXAudio.h"
|
||||
#include "OMXReader.h"
|
||||
#include "OMXPlayerVideo.h"
|
||||
#include "OMXPlayerAudio.h"
|
||||
#include "DllOMX.h"
|
||||
|
||||
enum PCMChannels *m_pChannelMap = NULL;
|
||||
unsigned int g_abort = false;
|
||||
bool m_bMpeg = false;
|
||||
bool m_passthrough = false;
|
||||
bool m_Deinterlace = false;
|
||||
bool m_HWDecode = false;
|
||||
CStdString deviceString = "omx:local";
|
||||
int m_use_hw_audio = false;
|
||||
bool m_Pause = false;
|
||||
OMXReader m_omx_reader;
|
||||
int m_audio_index_use = -1;
|
||||
bool m_buffer_empty = true;
|
||||
bool m_thread_player = false;
|
||||
int64_t m_audio_offset_ms = 0;
|
||||
OMXClock *m_av_clock = NULL;
|
||||
COMXStreamInfo m_hints_audio;
|
||||
COMXStreamInfo m_hints_video;
|
||||
OMXPacket *m_omx_pkt = NULL;
|
||||
bool m_hdmi_clock_sync = false;
|
||||
bool m_stop = false;
|
||||
bool m_show_subtitle = false;
|
||||
bool m_subtitle_index = 0;
|
||||
DllBcmHost m_BcmHost;
|
||||
OMXPlayerVideo m_player_video;
|
||||
OMXPlayerAudio m_player_audio;
|
||||
int m_tv_show_info = 0;
|
||||
bool m_has_video = false;
|
||||
bool m_has_audio = false;
|
||||
bool m_has_subtitle = false;
|
||||
|
||||
enum{ERROR=-1,SUCCESS,ONEBYTE};
|
||||
|
||||
static struct termios orig_termios;
|
||||
static void restore_termios (int status, void * arg)
|
||||
{
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &orig_termios);
|
||||
}
|
||||
|
||||
void sig_handler(int s)
|
||||
{
|
||||
printf("strg-c catched\n");
|
||||
g_abort = true;
|
||||
}
|
||||
|
||||
void print_usage()
|
||||
{
|
||||
printf("Usage: omxplayer [OPTIONS] [FILE]\n");
|
||||
printf("Options :\n");
|
||||
printf(" -h / --help print this help\n");
|
||||
printf(" -a / --alang language audio language : e.g. ger\n");
|
||||
printf(" -n / --aidx index audio stream index : e.g. 1\n");
|
||||
printf(" -o / --adev device audio out device : e.g. hdmi/local\n");
|
||||
printf(" -i / --info dump stream format and exit\n");
|
||||
printf(" -s / --stats pts and buffer stats\n");
|
||||
printf(" -p / --passthrough audio passthrough\n");
|
||||
printf(" -d / --deinterlace deinterlacing\n");
|
||||
printf(" -w / --hw hw audio decoding\n");
|
||||
printf(" -3 / --3d switch tv into 3d mode\n");
|
||||
printf(" -y / --hdmiclocksync adjust display refresh rate to match video\n");
|
||||
printf(" -t / --sid index show subtitle with index\n");
|
||||
}
|
||||
|
||||
void SetSpeed(int iSpeed)
|
||||
{
|
||||
if(!m_av_clock)
|
||||
return;
|
||||
|
||||
if(iSpeed < OMX_PLAYSPEED_PAUSE)
|
||||
return;
|
||||
|
||||
m_omx_reader.SetSpeed(iSpeed);
|
||||
|
||||
if(m_av_clock->OMXPlaySpeed() != OMX_PLAYSPEED_PAUSE && iSpeed == OMX_PLAYSPEED_PAUSE)
|
||||
m_Pause = true;
|
||||
else if(m_av_clock->OMXPlaySpeed() == OMX_PLAYSPEED_PAUSE && iSpeed != OMX_PLAYSPEED_PAUSE)
|
||||
m_Pause = false;
|
||||
|
||||
m_av_clock->OMXSpeed(iSpeed);
|
||||
}
|
||||
|
||||
void FlushStreams()
|
||||
{
|
||||
if(m_av_clock)
|
||||
m_av_clock->OMXPause();
|
||||
|
||||
if(m_has_video)
|
||||
m_player_video.Flush();
|
||||
|
||||
if(m_has_audio)
|
||||
m_player_audio.Flush();
|
||||
|
||||
if(m_omx_pkt)
|
||||
{
|
||||
m_omx_reader.FreePacket(m_omx_pkt);
|
||||
m_omx_pkt = NULL;
|
||||
}
|
||||
|
||||
if(m_av_clock)
|
||||
{
|
||||
m_av_clock->OMXReset();
|
||||
m_av_clock->OMXResume();
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct termios new_termios;
|
||||
|
||||
tcgetattr(STDIN_FILENO, &orig_termios);
|
||||
|
||||
new_termios = orig_termios;
|
||||
new_termios.c_lflag &= ~(ICANON | ECHO | ECHOCTL | ECHONL);
|
||||
new_termios.c_cflag |= HUPCL;
|
||||
new_termios.c_cc[VMIN] = 0;
|
||||
|
||||
CStdString last_sub = "";
|
||||
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &new_termios);
|
||||
on_exit(restore_termios, &orig_termios);
|
||||
|
||||
CStdString m_filename;
|
||||
double m_incr = 0;
|
||||
CRBP g_RBP;
|
||||
COMXCore g_OMX;
|
||||
bool m_stats = false;
|
||||
bool m_dump_format = false;
|
||||
bool m_3d = false;
|
||||
double startpts = 0;
|
||||
TV_GET_STATE_RESP_T tv_state;
|
||||
|
||||
struct option longopts[] = {
|
||||
{ "info", no_argument, NULL, 'i' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "aidx", required_argument, NULL, 'n' },
|
||||
{ "adev", required_argument, NULL, 'o' },
|
||||
{ "stats", no_argument, NULL, 's' },
|
||||
{ "passthrough", no_argument, NULL, 'p' },
|
||||
{ "deinterlace", no_argument, NULL, 'd' },
|
||||
{ "hw", no_argument, NULL, 'w' },
|
||||
{ "3d", no_argument, NULL, '3' },
|
||||
{ "hdmiclocksync", no_argument, NULL, 'y' },
|
||||
{ "sid", required_argument, NULL, 't' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
int c;
|
||||
while ((c = getopt_long(argc, argv, "wihn:o:cslpd3yt:", longopts, NULL)) != -1)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'y':
|
||||
m_hdmi_clock_sync = true;
|
||||
break;
|
||||
case '3':
|
||||
m_3d = true;
|
||||
break;
|
||||
case 'd':
|
||||
m_Deinterlace = true;
|
||||
break;
|
||||
case 'w':
|
||||
m_use_hw_audio = true;
|
||||
break;
|
||||
case 'p':
|
||||
m_passthrough = true;
|
||||
break;
|
||||
case 's':
|
||||
m_stats = true;
|
||||
break;
|
||||
case 'o':
|
||||
deviceString = optarg;
|
||||
if(deviceString != CStdString("local") && deviceString != CStdString("hdmi"))
|
||||
{
|
||||
print_usage();
|
||||
return 0;
|
||||
}
|
||||
deviceString = "omx:" + deviceString;
|
||||
break;
|
||||
case 'i':
|
||||
m_dump_format = true;
|
||||
break;
|
||||
case 't':
|
||||
m_subtitle_index = atoi(optarg) - 1;
|
||||
if(m_subtitle_index < 0)
|
||||
m_subtitle_index = 0;
|
||||
m_show_subtitle = true;
|
||||
break;
|
||||
case 'n':
|
||||
m_audio_index_use = atoi(optarg) - 1;
|
||||
if(m_audio_index_use < 0)
|
||||
m_audio_index_use = 0;
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
case 'h':
|
||||
print_usage();
|
||||
return 0;
|
||||
break;
|
||||
case ':':
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind >= argc) {
|
||||
print_usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_filename = argv[optind];
|
||||
|
||||
CLog::Init("./");
|
||||
|
||||
g_RBP.Initialize();
|
||||
g_OMX.Initialize();
|
||||
|
||||
m_av_clock = new OMXClock();
|
||||
|
||||
m_thread_player = true;
|
||||
|
||||
if(!m_omx_reader.Open(m_filename.c_str(), m_dump_format))
|
||||
goto do_exit;
|
||||
|
||||
if(m_dump_format)
|
||||
goto do_exit;
|
||||
|
||||
m_bMpeg = m_omx_reader.IsMpegVideo();
|
||||
m_has_video = m_omx_reader.VideoStreamCount();
|
||||
m_has_audio = m_omx_reader.AudioStreamCount();
|
||||
m_has_subtitle = m_omx_reader.SubtitleStreamCount();
|
||||
|
||||
if(!m_av_clock->OMXInitialize(m_has_video, m_has_audio))
|
||||
goto do_exit;
|
||||
|
||||
if(m_hdmi_clock_sync && !m_av_clock->HDMIClockSync())
|
||||
goto do_exit;
|
||||
|
||||
m_omx_reader.GetHints(OMXSTREAM_AUDIO, m_hints_audio);
|
||||
m_omx_reader.GetHints(OMXSTREAM_VIDEO, m_hints_video);
|
||||
|
||||
if(m_audio_index_use != -1)
|
||||
m_omx_reader.SetActiveStream(OMXSTREAM_AUDIO, m_audio_index_use);
|
||||
|
||||
if(m_has_video && !m_player_video.Open(m_hints_video, m_av_clock, m_Deinterlace, m_bMpeg,
|
||||
m_has_audio, m_hdmi_clock_sync, m_thread_player))
|
||||
goto do_exit;
|
||||
|
||||
if(m_has_video)
|
||||
{
|
||||
int width = 1280;
|
||||
int height = 720;
|
||||
|
||||
if(m_hints_video.width <= 720)
|
||||
{
|
||||
width = 720; height = 576;
|
||||
}
|
||||
else if(m_hints_video.width <= 1280)
|
||||
{
|
||||
width = 1280; height = 720;
|
||||
}
|
||||
else
|
||||
{
|
||||
width = 1920; height = 1080;
|
||||
}
|
||||
|
||||
memset(&tv_state, 0, sizeof(TV_GET_STATE_RESP_T));
|
||||
m_BcmHost.vc_tv_get_state(&tv_state);
|
||||
|
||||
int32_t num_modes;
|
||||
HDMI_RES_GROUP_T prefer_group;
|
||||
int i = 0;
|
||||
uint32_t prefer_mode;
|
||||
#define TV_MAX_SUPPORTED_MODES 60
|
||||
TV_SUPPORTED_MODE_T supported_modes[TV_MAX_SUPPORTED_MODES];
|
||||
uint32_t group = HDMI_RES_GROUP_CEA;
|
||||
int mode = 1;
|
||||
|
||||
|
||||
if(m_filename.find("3DSBS") != string::npos)
|
||||
m_3d = true;
|
||||
|
||||
if(m_3d)
|
||||
{
|
||||
group = HDMI_RES_GROUP_CEA_3D;
|
||||
}
|
||||
else
|
||||
{
|
||||
group = HDMI_RES_GROUP_CEA;
|
||||
}
|
||||
|
||||
num_modes = m_BcmHost.vc_tv_hdmi_get_supported_modes((HDMI_RES_GROUP_T)group,
|
||||
supported_modes,
|
||||
TV_MAX_SUPPORTED_MODES,
|
||||
&prefer_group,
|
||||
&prefer_mode);
|
||||
|
||||
float last_diff = (float)m_player_video.GetFPS();
|
||||
if(m_3d)
|
||||
last_diff *= 2;
|
||||
|
||||
TV_SUPPORTED_MODE_T *tv_found = NULL;
|
||||
if (num_modes > 0 && prefer_group != HDMI_RES_GROUP_INVALID)
|
||||
{
|
||||
TV_SUPPORTED_MODE_T *tv = supported_modes;
|
||||
for (i=0; i<num_modes; i++, tv++)
|
||||
{
|
||||
float fps = ((group==HDMI_RES_GROUP_CEA_3D) ? (float)m_player_video.GetFPS() * 2.0f : (float)m_player_video.GetFPS());
|
||||
|
||||
if(tv->width == width && tv->height == height && fps <= (float)tv->frame_rate)
|
||||
{
|
||||
float diff = (float)tv->frame_rate - fps;
|
||||
if(diff < 0.0f)
|
||||
diff *= -1.0f;
|
||||
|
||||
if(diff < last_diff)
|
||||
{
|
||||
last_diff = diff;
|
||||
tv_found = tv;
|
||||
mode = supported_modes[i].code;
|
||||
}
|
||||
}
|
||||
else if( fps <= (float)tv->frame_rate && tv->width >= width && tv->height >= height)
|
||||
{
|
||||
float diff = (float)tv->frame_rate - fps;
|
||||
if(diff < 0.0f)
|
||||
diff *= -1.0f;
|
||||
|
||||
if(diff < last_diff)
|
||||
{
|
||||
last_diff = diff;
|
||||
tv_found = tv;
|
||||
mode = supported_modes[i].code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!tv_found)
|
||||
{
|
||||
tv = supported_modes;
|
||||
for (i=0; i<num_modes; i++, tv++)
|
||||
{
|
||||
if(tv->width == width && tv->height == height)
|
||||
{
|
||||
tv_found = tv;
|
||||
mode = supported_modes[i].code;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(tv_found)
|
||||
printf("Output mode %d: %dx%d@%d %s%s:%x\n", i, tv_found->width, tv_found->height,
|
||||
tv_found->frame_rate, tv_found->native?"N":"", tv_found->scan_mode?"I":"", tv_found->code);
|
||||
}
|
||||
|
||||
if(tv_found)
|
||||
m_BcmHost.vc_tv_hdmi_power_on_explicit(HDMI_MODE_HDMI, (HDMI_RES_GROUP_T)group, mode);
|
||||
|
||||
}
|
||||
|
||||
m_av_clock->OMXStateExecute();
|
||||
m_av_clock->SetSpeed(DVD_PLAYSPEED_NORMAL);
|
||||
|
||||
if(m_has_subtitle && m_subtitle_index > (m_omx_reader.SubtitleStreamCount() - 1))
|
||||
{
|
||||
m_subtitle_index = m_omx_reader.SubtitleStreamCount() - 1;
|
||||
m_omx_reader.SetActiveStream(OMXSTREAM_SUBTITLE, m_subtitle_index);
|
||||
m_show_subtitle = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_show_subtitle = false;
|
||||
}
|
||||
|
||||
m_omx_reader.GetHints(OMXSTREAM_AUDIO, m_hints_audio);
|
||||
|
||||
if(m_has_audio && !m_player_audio.Open(m_hints_audio, m_av_clock, &m_omx_reader, deviceString,
|
||||
m_passthrough, m_use_hw_audio, m_thread_player))
|
||||
goto do_exit;
|
||||
|
||||
m_av_clock->OMXStateExecute();
|
||||
m_av_clock->OMXReset();
|
||||
m_av_clock->OMXResume();
|
||||
|
||||
struct timespec starttime, endtime;
|
||||
|
||||
while(!m_stop)
|
||||
{
|
||||
int ch[8];
|
||||
int chnum = 0;
|
||||
|
||||
if(g_abort)
|
||||
goto do_exit;
|
||||
|
||||
while((ch[chnum] = getchar()) != EOF) chnum++;
|
||||
if (chnum > 1) ch[0] = ch[chnum - 1] | (ch[chnum - 2] << 8);
|
||||
|
||||
switch(ch[0])
|
||||
{
|
||||
case 'z':
|
||||
m_tv_show_info = !m_tv_show_info;
|
||||
vc_tv_show_info(m_tv_show_info);
|
||||
break;
|
||||
case '1':
|
||||
SetSpeed(m_av_clock->OMXPlaySpeed() - 1);
|
||||
break;
|
||||
case '2':
|
||||
SetSpeed(m_av_clock->OMXPlaySpeed() + 1);
|
||||
break;
|
||||
case 'j':
|
||||
m_omx_reader.SetActiveStream(OMXSTREAM_AUDIO, m_omx_reader.GetAudioIndex() - 1);
|
||||
break;
|
||||
case 'k':
|
||||
m_omx_reader.SetActiveStream(OMXSTREAM_AUDIO, m_omx_reader.GetAudioIndex() + 1);
|
||||
break;
|
||||
case 'i':
|
||||
if(m_omx_reader.GetChapterCount() > 0)
|
||||
{
|
||||
m_omx_reader.SeekChapter(m_omx_reader.GetChapter() - 1, &startpts);
|
||||
FlushStreams();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_incr = -600.0;
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
if(m_omx_reader.GetChapterCount() > 0)
|
||||
{
|
||||
m_omx_reader.SeekChapter(m_omx_reader.GetChapter() + 1, &startpts);
|
||||
FlushStreams();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_incr = 600.0;
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
if(m_omx_reader.GetSubtitleIndex() > 0)
|
||||
{
|
||||
m_omx_reader.SetActiveStream(OMXSTREAM_SUBTITLE, m_omx_reader.GetSubtitleIndex() - 1);
|
||||
m_player_video.FlushSubtitles();
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
if(m_omx_reader.GetSubtitleIndex() > 0)
|
||||
{
|
||||
m_omx_reader.SetActiveStream(OMXSTREAM_SUBTITLE, m_omx_reader.GetSubtitleIndex() + 1);
|
||||
m_player_video.FlushSubtitles();
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
m_show_subtitle = !m_show_subtitle;
|
||||
break;
|
||||
case 'q':
|
||||
m_stop = true;
|
||||
goto do_exit;
|
||||
break;
|
||||
case 0x5b44: // key left
|
||||
m_incr = -30.0;
|
||||
break;
|
||||
case 0x5b43: // key right
|
||||
m_incr = 30.0;
|
||||
break;
|
||||
case 0x5b41: // key up
|
||||
m_incr = 600.0;
|
||||
break;
|
||||
case 0x5b42: // key down
|
||||
m_incr = -600.0;
|
||||
break;
|
||||
case ' ':
|
||||
case 'p':
|
||||
m_Pause = !m_Pause;
|
||||
if(m_Pause)
|
||||
{
|
||||
SetSpeed(OMX_PLAYSPEED_PAUSE);
|
||||
m_av_clock->OMXPause();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetSpeed(OMX_PLAYSPEED_NORMAL);
|
||||
m_av_clock->OMXResume();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(m_Pause)
|
||||
{
|
||||
OMXClock::OMXSleep(2);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(m_incr != 0 && !m_bMpeg)
|
||||
{
|
||||
int seek_flags = 0;
|
||||
double seek_pos = 0;
|
||||
double pts = 0;
|
||||
|
||||
pts = m_av_clock->GetPTS();
|
||||
|
||||
seek_pos = (pts / DVD_TIME_BASE) + m_incr;
|
||||
seek_flags = m_incr < 0 ? AVSEEK_FLAG_BACKWARD : 0;
|
||||
|
||||
if(seek_pos < 0)
|
||||
seek_pos = 0;
|
||||
|
||||
seek_pos *= 1000;
|
||||
|
||||
m_incr = 0;
|
||||
|
||||
if(m_omx_reader.SeekTime(seek_pos, seek_flags, &startpts))
|
||||
FlushStreams();
|
||||
}
|
||||
|
||||
/* when the audio buffer runs under 0.1 seconds we buffer up */
|
||||
if(m_has_audio)
|
||||
{
|
||||
if(m_player_audio.GetDelay() < 0.1f && !m_buffer_empty)
|
||||
{
|
||||
if(!m_av_clock->OMXIsPaused())
|
||||
{
|
||||
m_av_clock->OMXPause();
|
||||
//printf("buffering start\n");
|
||||
m_buffer_empty = true;
|
||||
clock_gettime(CLOCK_REALTIME, &starttime);
|
||||
}
|
||||
}
|
||||
if(m_player_audio.GetDelay() > (AUDIO_BUFFER_SECONDS * 0.75f) && m_buffer_empty)
|
||||
{
|
||||
if(m_av_clock->OMXIsPaused())
|
||||
{
|
||||
m_av_clock->OMXResume();
|
||||
//printf("buffering end\n");
|
||||
m_buffer_empty = false;
|
||||
}
|
||||
}
|
||||
if(m_buffer_empty)
|
||||
{
|
||||
clock_gettime(CLOCK_REALTIME, &endtime);
|
||||
if((endtime.tv_sec - starttime.tv_sec) > 1)
|
||||
{
|
||||
m_buffer_empty = false;
|
||||
m_av_clock->OMXResume();
|
||||
//printf("buffering timed out\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!m_omx_pkt)
|
||||
m_omx_pkt = m_omx_reader.Read();
|
||||
|
||||
if(m_omx_pkt && m_omx_reader.IsActive(OMXSTREAM_VIDEO, m_omx_pkt->stream_index))
|
||||
{
|
||||
if(m_omx_pkt->pts != DVD_NOPTS_VALUE)
|
||||
m_omx_pkt->pts += (m_audio_offset_ms * 1000);
|
||||
if(m_omx_pkt->dts != DVD_NOPTS_VALUE)
|
||||
m_omx_pkt->dts += (m_audio_offset_ms * 1000);
|
||||
|
||||
if(m_player_video.AddPacket(m_omx_pkt))
|
||||
m_omx_pkt = NULL;
|
||||
else
|
||||
OMXClock::OMXSleep(10);
|
||||
|
||||
if(m_tv_show_info)
|
||||
{
|
||||
char response[80];
|
||||
vc_gencmd(response, sizeof response, "render_bar 4 video_fifo %d %d %d %d",
|
||||
m_player_video.GetDecoderBufferSize()-m_player_video.GetDecoderFreeSpace(),
|
||||
0 , 0, m_player_video.GetDecoderBufferSize());
|
||||
vc_gencmd(response, sizeof response, "render_bar 5 audio_fifo %d %d %d %d",
|
||||
(int)(100.0*m_player_audio.GetDelay()), 0, 0, 100*AUDIO_BUFFER_SECONDS);
|
||||
}
|
||||
}
|
||||
else if(m_omx_pkt && m_omx_pkt->codec_type == AVMEDIA_TYPE_AUDIO)
|
||||
{
|
||||
if(m_player_audio.AddPacket(m_omx_pkt))
|
||||
m_omx_pkt = NULL;
|
||||
else
|
||||
OMXClock::OMXSleep(10);
|
||||
}
|
||||
else if(m_omx_pkt && m_omx_reader.IsActive(OMXSTREAM_SUBTITLE, m_omx_pkt->stream_index))
|
||||
{
|
||||
if(m_omx_pkt->size && (m_omx_pkt->hints.codec == CODEC_ID_TEXT ||
|
||||
m_omx_pkt->hints.codec == CODEC_ID_SSA))
|
||||
{
|
||||
if(m_player_video.AddPacket(m_omx_pkt))
|
||||
m_omx_pkt = NULL;
|
||||
else
|
||||
OMXClock::OMXSleep(10);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_omx_reader.FreePacket(m_omx_pkt);
|
||||
m_omx_pkt = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_omx_pkt)
|
||||
{
|
||||
m_omx_reader.FreePacket(m_omx_pkt);
|
||||
m_omx_pkt = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* player got in an error state */
|
||||
if(m_player_audio.Error())
|
||||
{
|
||||
printf("audio player error. emergency exit!!!\n");
|
||||
goto do_exit;
|
||||
}
|
||||
|
||||
CStdString strSubTitle = m_player_video.GetText();
|
||||
if(strSubTitle.length() && m_show_subtitle)
|
||||
{
|
||||
if(last_sub != strSubTitle)
|
||||
{
|
||||
last_sub = strSubTitle;
|
||||
printf("Text : %s\n", strSubTitle.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if(m_stats)
|
||||
{
|
||||
printf("V : %8.02f %8d %8d A : %8.02f %8.02f Cv : %8d Ca : %8d \r",
|
||||
m_player_video.GetCurrentPTS() / DVD_TIME_BASE, m_player_video.GetDecoderBufferSize(),
|
||||
m_player_video.GetDecoderFreeSpace(), m_player_audio.GetCurrentPTS() / DVD_TIME_BASE,
|
||||
m_player_audio.GetDelay(), m_player_video.GetCached(), m_player_audio.GetCached());
|
||||
}
|
||||
if(m_omx_reader.IsEof())
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
do_exit:
|
||||
printf("\n");
|
||||
|
||||
if(!m_stop)
|
||||
{
|
||||
if(m_has_audio)
|
||||
m_player_audio.WaitCompletion();
|
||||
else if(m_has_video)
|
||||
m_player_video.WaitCompletion();
|
||||
}
|
||||
|
||||
m_BcmHost.vc_tv_hdmi_power_on_best(tv_state.width, tv_state.height, tv_state.frame_rate, HDMI_NONINTERLACED,
|
||||
(EDID_MODE_MATCH_FLAG_T)(HDMI_MODE_MATCH_FRAMERATE|HDMI_MODE_MATCH_RESOLUTION|HDMI_MODE_MATCH_SCANMODE));
|
||||
|
||||
m_av_clock->OMXStop();
|
||||
m_av_clock->OMXStateIdle();
|
||||
|
||||
m_player_video.Close();
|
||||
m_player_audio.Close();
|
||||
|
||||
if(m_omx_pkt)
|
||||
{
|
||||
m_omx_reader.FreePacket(m_omx_pkt);
|
||||
m_omx_pkt = NULL;
|
||||
}
|
||||
|
||||
m_omx_reader.Close();
|
||||
|
||||
vc_tv_show_info(0);
|
||||
|
||||
g_OMX.Deinitialize();
|
||||
g_RBP.Deinitialize();
|
||||
|
||||
printf("have a nice day ;)\n");
|
||||
return 1;
|
||||
}
|
||||
11
profiler.sh
Normal file
11
profiler.sh
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh
|
||||
|
||||
insmod /lib/modules/3.1.10+/kernel/arch/arm/oprofile/oprofile.ko timer=1
|
||||
opcontrol --init
|
||||
opcontrol --vmlinux=/boot/vmlinux
|
||||
opcontrol --start
|
||||
|
||||
./omxplayer.bin -s -o hdmi /media/net/1080p/Gone\ in\ Sixty\ Seconds\ 2000.mkv
|
||||
|
||||
opcontrol --dump
|
||||
opreport -l
|
||||
295
system.h
Normal file
295
system.h
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H) && !defined(TARGET_WINDOWS)
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/*****************
|
||||
* All platforms
|
||||
*****************/
|
||||
#define HAS_DVD_SWSCALE
|
||||
#define HAS_DVDPLAYER
|
||||
#define HAS_EVENT_SERVER
|
||||
#define HAS_KARAOKE
|
||||
#define HAS_SCREENSAVER
|
||||
#define HAS_PYTHON
|
||||
#define HAS_SYSINFO
|
||||
#define HAS_UPNP
|
||||
#define HAS_VIDEO_PLAYBACK
|
||||
#define HAS_VISUALISATION
|
||||
|
||||
#ifdef HAVE_LIBMICROHTTPD
|
||||
#define HAS_WEB_SERVER
|
||||
#define HAS_WEB_INTERFACE
|
||||
#endif
|
||||
|
||||
#define HAS_JSONRPC
|
||||
#define HAS_HTTPAPI
|
||||
|
||||
#ifdef USE_ASAP_CODEC
|
||||
#define HAS_ASAP_CODEC
|
||||
#endif
|
||||
|
||||
#define HAS_FILESYSTEM
|
||||
#define HAS_FILESYSTEM_CDDA
|
||||
#define HAS_FILESYSTEM_RTV
|
||||
#define HAS_FILESYSTEM_DAAP
|
||||
#define HAS_FILESYSTEM_SAP
|
||||
#define HAS_FILESYSTEM_VTP
|
||||
#define HAS_FILESYSTEM_HTSP
|
||||
|
||||
#ifdef HAVE_LIBSMBCLIENT
|
||||
#define HAS_FILESYSTEM_SMB
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBNFS
|
||||
#define HAS_FILESYSTEM_NFS
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBAFPCLIENT
|
||||
#define HAS_FILESYSTEM_AFP
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBPLIST
|
||||
#define HAS_AIRPLAY
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBSHAIRPORT
|
||||
#define HAS_AIRTUNES
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* Non-free Components
|
||||
**********************/
|
||||
|
||||
#if defined(TARGET_WINDOWS)
|
||||
#define HAS_FILESYSTEM_RAR
|
||||
#else
|
||||
#if defined(HAVE_XBMC_NONFREE)
|
||||
#define HAS_FILESYSTEM_RAR
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*****************
|
||||
* Win32 Specific
|
||||
*****************/
|
||||
|
||||
#if defined(TARGET_WINDOWS)
|
||||
#define HAS_SDL
|
||||
#define HAS_SDL_JOYSTICK
|
||||
#define HAS_DVD_DRIVE
|
||||
#define HAS_WIN32_NETWORK
|
||||
#define HAS_IRSERVERSUITE
|
||||
#define HAS_AUDIO
|
||||
#define HAVE_LIBCRYSTALHD 2
|
||||
#define HAS_WEB_SERVER
|
||||
#define HAS_WEB_INTERFACE
|
||||
#define HAVE_LIBSSH
|
||||
#define HAS_LIBRTMP
|
||||
#define HAVE_LIBBLURAY
|
||||
#define HAS_ASAP_CODEC
|
||||
#define HAVE_YAJL_YAJL_VERSION_H
|
||||
#define HAS_FILESYSTEM_SMB
|
||||
#define HAS_FILESYSTEM_NFS
|
||||
#endif
|
||||
|
||||
/*****************
|
||||
* Mac Specific
|
||||
*****************/
|
||||
|
||||
#if defined(TARGET_DARWIN)
|
||||
#if defined(TARGET_DARWIN_OSX)
|
||||
#define HAS_GL
|
||||
#define HAS_SDL
|
||||
#define HAS_SDL_AUDIO
|
||||
#define HAS_SDL_OPENGL
|
||||
#define HAS_SDL_WIN_EVENTS
|
||||
#endif
|
||||
#define HAS_ZEROCONF
|
||||
#define HAS_LINUX_NETWORK
|
||||
#endif
|
||||
|
||||
/*****************
|
||||
* Linux Specific
|
||||
*****************/
|
||||
|
||||
#if defined(TARGET_LINUX)
|
||||
|
||||
#if defined(HAVE_LIBAVAHI_COMMON) && defined(HAVE_LIBAVAHI_CLIENT)
|
||||
#define HAS_ZEROCONF
|
||||
#define HAS_AVAHI
|
||||
#endif
|
||||
#define HAS_LCD
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
#define HAS_DBUS
|
||||
#define HAS_DBUS_SERVER
|
||||
#endif
|
||||
|
||||
#define HAS_GL
|
||||
#ifdef HAVE_X11
|
||||
#define HAS_GLX
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SDL
|
||||
#define HAS_SDL
|
||||
#ifndef HAS_SDL_OPENGL
|
||||
#define HAS_SDL_OPENGL
|
||||
#define HAS_SDL_AUDIO
|
||||
#define HAS_SDL_WIN_EVENTS
|
||||
#endif
|
||||
#else
|
||||
#define HAS_LINUX_EVENTS
|
||||
#endif
|
||||
|
||||
#define HAS_LINUX_NETWORK
|
||||
#define HAS_LIRC
|
||||
|
||||
#ifdef HAVE_LIBPULSE
|
||||
#define HAS_PULSEAUDIO
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBXRANDR
|
||||
#define HAS_XRANDR
|
||||
#endif
|
||||
|
||||
#define HAS_AIRPLAY
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBSSH
|
||||
#define HAS_FILESYSTEM_SFTP
|
||||
#endif
|
||||
|
||||
/*****************
|
||||
* Git revision
|
||||
*****************/
|
||||
|
||||
#if defined(TARGET_DARWIN)
|
||||
#include "../git_revision.h"
|
||||
#endif
|
||||
|
||||
#ifndef GIT_REV
|
||||
#define GIT_REV "Unknown"
|
||||
#endif
|
||||
|
||||
/****************************************
|
||||
* Additional platform specific includes
|
||||
****************************************/
|
||||
|
||||
#if defined(TARGET_WINDOWS)
|
||||
#include <windows.h>
|
||||
#define DIRECTINPUT_VERSION 0x0800
|
||||
#include "mmsystem.h"
|
||||
#include "DInput.h"
|
||||
#include "DSound.h"
|
||||
#define DSSPEAKER_USE_DEFAULT DSSPEAKER_STEREO
|
||||
#define LPDIRECTSOUND8 LPDIRECTSOUND
|
||||
#undef GetFreeSpace
|
||||
#include "PlatformInclude.h"
|
||||
#ifdef HAS_DX
|
||||
#include "D3D9.h" // On Win32, we're always using DirectX for something, whether it be the actual rendering
|
||||
#include "D3DX9.h" // or the reference video clock.
|
||||
#else
|
||||
#include <d3d9types.h>
|
||||
#endif
|
||||
#ifdef HAS_SDL
|
||||
#include "SDL\SDL.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_POSIX)
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include "PlatformDefs.h"
|
||||
#endif
|
||||
|
||||
// ARM does not support certain features... disable them here!
|
||||
#ifdef _ARMEL
|
||||
#undef HAS_AVAHI
|
||||
#undef HAS_ZEROCONF
|
||||
#undef HAS_VISUALISATION
|
||||
#undef HAS_FILESYSTEM_HTSP
|
||||
#endif
|
||||
|
||||
// EGL detected. Dont use GLX!
|
||||
#ifdef HAVE_LIBEGL
|
||||
#undef HAS_GLX
|
||||
#define HAS_EGL
|
||||
#endif
|
||||
|
||||
// GLES2.0 detected. Dont use GL!
|
||||
#ifdef HAVE_LIBGLESV2
|
||||
#undef HAS_GL
|
||||
#define HAS_GLES 2
|
||||
#endif
|
||||
|
||||
// GLES1.0 detected. Dont use GL!
|
||||
#ifdef HAVE_LIBGLES
|
||||
#undef HAS_GL
|
||||
#define HAS_GLES 1
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAS_GL
|
||||
#if defined(TARGET_WINDOWS)
|
||||
#include "GL/glew.h"
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
//#include <GL/wglext.h>
|
||||
#elif defined(TARGET_DARWIN)
|
||||
#include <GL/glew.h>
|
||||
#include <OpenGL/gl.h>
|
||||
#elif defined(TARGET_LINUX)
|
||||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_GLES == 2
|
||||
#if defined(TARGET_DARWIN)
|
||||
#include <OpenGLES/ES2/gl.h>
|
||||
#include <OpenGLES/ES2/glext.h>
|
||||
#else
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAS_DVD_DRIVE
|
||||
#define HAS_CDDA_RIPPER
|
||||
#endif
|
||||
|
||||
#define SAFE_DELETE(p) do { delete (p); (p)=NULL; } while (0)
|
||||
#define SAFE_DELETE_ARRAY(p) do { delete[] (p); (p)=NULL; } while (0)
|
||||
#define SAFE_RELEASE(p) do { if(p) { (p)->Release(); (p)=NULL; } } while (0)
|
||||
|
||||
// Useful pixel colour manipulation macros
|
||||
#define GET_A(color) ((color >> 24) & 0xFF)
|
||||
#define GET_R(color) ((color >> 16) & 0xFF)
|
||||
#define GET_G(color) ((color >> 8) & 0xFF)
|
||||
#define GET_B(color) ((color >> 0) & 0xFF)
|
||||
|
||||
209
utils/MathUtils.h
Normal file
209
utils/MathUtils.h
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
#pragma once
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
#include <stdio.h>
|
||||
/*! \brief Math utility class.
|
||||
Note that the test() routine should return true for all implementations
|
||||
|
||||
See http://ldesoras.free.fr/doc/articles/rounding_en.pdf for an explanation
|
||||
of the technique used on x86.
|
||||
*/
|
||||
namespace MathUtils
|
||||
{
|
||||
// GCC does something stupid with optimization on release builds if we try
|
||||
// to assert in these functions
|
||||
|
||||
/*! \brief Round to nearest integer.
|
||||
This routine does fast rounding to the nearest integer.
|
||||
In the case (k + 0.5 for any integer k) we round up to k+1, and in all other
|
||||
instances we should return the nearest integer.
|
||||
Thus, { -1.5, -0.5, 0.5, 1.5 } is rounded to { -1, 0, 1, 2 }.
|
||||
It preserves the property that round(k) - round(k-1) = 1 for all doubles k.
|
||||
|
||||
Make sure MathUtils::test() returns true for each implementation.
|
||||
\sa truncate_int, test
|
||||
*/
|
||||
inline int round_int (double x)
|
||||
{
|
||||
assert(x > static_cast<double>(INT_MIN / 2) - 1.0);
|
||||
assert(x < static_cast <double>(INT_MAX / 2) + 1.0);
|
||||
const float round_to_nearest = 0.5f;
|
||||
int i;
|
||||
|
||||
#ifndef _LINUX
|
||||
__asm
|
||||
{
|
||||
fld x
|
||||
fadd st, st (0)
|
||||
fadd round_to_nearest
|
||||
fistp i
|
||||
sar i, 1
|
||||
}
|
||||
#else
|
||||
#if defined(__powerpc__) || defined(__ppc__)
|
||||
i = floor(x + round_to_nearest);
|
||||
#elif defined(__arm__)
|
||||
// From 'ARM®v7-M Architecture Reference Manual' page A7-569:
|
||||
// "The floating-point to integer operation (vcvt) [normally] uses the Round towards Zero rounding mode"
|
||||
// Because of this...we must use some less-than-straightforward logic to perform this operation without
|
||||
// changing the rounding mode flags
|
||||
|
||||
/* The assembly below implements the following logic:
|
||||
if (x < 0)
|
||||
inc = -0.5f
|
||||
else
|
||||
inc = 0.5f
|
||||
int_val = trunc(x+inc);
|
||||
err = x - int_val;
|
||||
if (err == 0.5f)
|
||||
int_val++;
|
||||
return int_val;
|
||||
*/
|
||||
/*
|
||||
__asm__ __volatile__ (
|
||||
"vmov.F64 d1,%[rnd_val] \n\t" // Copy round_to_nearest into a working register (d1 = 0.5)
|
||||
"fcmpezd %P[value] \n\t" // Check value against zero (value == 0?)
|
||||
"fmstat \n\t" // Copy the floating-point status flags into the general-purpose status flags
|
||||
"it mi \n\t"
|
||||
"vnegmi.F64 d1, d1 \n\t" // if N-flag is set, negate round_to_nearest (if (value < 0) d1 = -1 * d1)
|
||||
"vadd.F64 d1,%P[value],d1 \n\t" // Add round_to_nearest to value, store result in working register (d1 += value)
|
||||
"vcvt.S32.F64 s3,d1 \n\t" // Truncate(round towards zero) (s3 = (int)d1)
|
||||
"vmov %[result],s3 \n\t" // Store the integer result in a general-purpose register (result = s3)
|
||||
"vcvt.F64.S32 d1,s3 \n\t" // Convert back to floating-point (d1 = (double)s3)
|
||||
"vsub.F64 d1,%P[value],d1 \n\t" // Calculate the error (d1 = value - d1)
|
||||
"vmov.F64 d2,%[rnd_val] \n\t" // d2 = 0.5;
|
||||
"fcmped d1, d2 \n\t" // (d1 == 0.5?)
|
||||
"fmstat \n\t" // Copy the floating-point status flags into the general-purpose status flags
|
||||
"it eq \n\t"
|
||||
"addeq %[result],#1 \n\t" // (if (d1 == d2) result++;)
|
||||
: [result] "=r"(i) // Outputs
|
||||
: [rnd_val] "Dv" (round_to_nearest), [value] "w"(x) // Inputs
|
||||
: "d1", "d2", "s3" // Clobbers
|
||||
);
|
||||
*/
|
||||
i = floor(x + round_to_nearest);
|
||||
#else
|
||||
__asm__ __volatile__ (
|
||||
"fadd %%st\n\t"
|
||||
"fadd %%st(1)\n\t"
|
||||
"fistpl %0\n\t"
|
||||
"sarl $1, %0\n"
|
||||
: "=m"(i) : "u"(round_to_nearest), "t"(x) : "st"
|
||||
);
|
||||
#endif
|
||||
#endif
|
||||
return (i);
|
||||
}
|
||||
|
||||
/*! \brief Truncate to nearest integer.
|
||||
This routine does fast truncation to an integer.
|
||||
It should simply drop the fractional portion of the floating point number.
|
||||
|
||||
Make sure MathUtils::test() returns true for each implementation.
|
||||
\sa round_int, test
|
||||
*/
|
||||
inline int truncate_int(double x)
|
||||
{
|
||||
assert(x > static_cast<double>(INT_MIN / 2) - 1.0);
|
||||
assert(x < static_cast <double>(INT_MAX / 2) + 1.0);
|
||||
|
||||
#if !defined(__powerpc__) && !defined(__ppc__) && !defined(__arm__)
|
||||
const float round_towards_m_i = -0.5f;
|
||||
#endif
|
||||
int i;
|
||||
|
||||
#ifndef _LINUX
|
||||
__asm
|
||||
{
|
||||
fld x
|
||||
fadd st, st (0)
|
||||
fabs
|
||||
fadd round_towards_m_i
|
||||
fistp i
|
||||
sar i, 1
|
||||
}
|
||||
#else
|
||||
#if defined(__powerpc__) || defined(__ppc__)
|
||||
return (int)x;
|
||||
#elif defined(__arm__)
|
||||
/*
|
||||
__asm__ __volatile__ (
|
||||
"vcvt.S32.F64 %[result],%P[value] \n\t" // Truncate(round towards zero) and store the result
|
||||
: [result] "=w"(i) // Outputs
|
||||
: [value] "w"(x) // Inputs
|
||||
);
|
||||
return i;
|
||||
*/
|
||||
return (int)x;
|
||||
#else
|
||||
__asm__ __volatile__ (
|
||||
"fadd %%st\n\t"
|
||||
"fabs\n\t"
|
||||
"fadd %%st(1)\n\t"
|
||||
"fistpl %0\n\t"
|
||||
"sarl $1, %0\n"
|
||||
: "=m"(i) : "u"(round_towards_m_i), "t"(x) : "st"
|
||||
);
|
||||
#endif
|
||||
#endif
|
||||
if (x < 0)
|
||||
i = -i;
|
||||
return (i);
|
||||
}
|
||||
|
||||
inline int64_t abs(int64_t a)
|
||||
{
|
||||
return (a < 0) ? -a : a;
|
||||
}
|
||||
|
||||
inline void hack()
|
||||
{
|
||||
// stupid hack to keep compiler from dropping these
|
||||
// functions as unused
|
||||
MathUtils::round_int(0.0);
|
||||
MathUtils::truncate_int(0.0);
|
||||
MathUtils::abs(0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*! \brief test routine for round_int and truncate_int
|
||||
Must return true on all platforms.
|
||||
*/
|
||||
inline bool test()
|
||||
{
|
||||
for (int i = -8; i < 8; ++i)
|
||||
{
|
||||
double d = 0.25*i;
|
||||
int r = (i < 0) ? (i - 1) / 4 : (i + 2) / 4;
|
||||
int t = i / 4;
|
||||
if (round_int(d) != r || truncate_int(d) != t)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
} // namespace MathUtils
|
||||
|
||||
795
utils/PCMRemap.cpp
Normal file
795
utils/PCMRemap.cpp
Normal file
|
|
@ -0,0 +1,795 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2010 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __STDC_LIMIT_MACROS
|
||||
#define __STDC_LIMIT_MACROS
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "MathUtils.h"
|
||||
#include "PCMRemap.h"
|
||||
#include "utils/log.h"
|
||||
#ifdef _WIN32
|
||||
#include "../win32/PlatformDefs.h"
|
||||
#endif
|
||||
|
||||
static enum PCMChannels PCMLayoutMap[PCM_MAX_LAYOUT][PCM_MAX_CH + 1] =
|
||||
{
|
||||
/* 2.0 */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_INVALID},
|
||||
/* 2.1 */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_LOW_FREQUENCY, PCM_INVALID},
|
||||
/* 3.0 */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_INVALID},
|
||||
/* 3.1 */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_LOW_FREQUENCY, PCM_INVALID},
|
||||
/* 4.0 */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_BACK_LEFT, PCM_BACK_RIGHT, PCM_INVALID},
|
||||
/* 4.1 */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_BACK_LEFT, PCM_BACK_RIGHT, PCM_LOW_FREQUENCY, PCM_INVALID},
|
||||
/* 5.0 */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_BACK_LEFT, PCM_BACK_RIGHT, PCM_INVALID},
|
||||
/* 5.1 */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_BACK_LEFT, PCM_BACK_RIGHT, PCM_LOW_FREQUENCY, PCM_INVALID},
|
||||
/* 7.0 */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_SIDE_LEFT, PCM_SIDE_RIGHT, PCM_BACK_LEFT, PCM_BACK_RIGHT, PCM_INVALID},
|
||||
/* 7.1 */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_SIDE_LEFT, PCM_SIDE_RIGHT, PCM_BACK_LEFT, PCM_BACK_RIGHT, PCM_LOW_FREQUENCY, PCM_INVALID}
|
||||
};
|
||||
|
||||
/*
|
||||
map missing output into channel @ volume level
|
||||
the order of this table is important, mix tables can not depend on channels that have not been defined yet
|
||||
eg, FC can only be mixed into FL, FR as they are the only channels that have been defined
|
||||
*/
|
||||
#define PCM_MAX_MIX 3
|
||||
static struct PCMMapInfo PCMDownmixTable[PCM_MAX_CH][PCM_MAX_MIX] =
|
||||
{
|
||||
/* PCM_FRONT_LEFT */
|
||||
{
|
||||
{PCM_INVALID}
|
||||
},
|
||||
/* PCM_FRONT_RIGHT */
|
||||
{
|
||||
{PCM_INVALID}
|
||||
},
|
||||
/* PCM_FRONT_CENTER */
|
||||
{
|
||||
{PCM_FRONT_LEFT_OF_CENTER , 1.0},
|
||||
{PCM_FRONT_RIGHT_OF_CENTER, 1.0},
|
||||
{PCM_INVALID}
|
||||
},
|
||||
/* PCM_LOW_FREQUENCY */
|
||||
{
|
||||
/*
|
||||
A/52B 7.8 paragraph 2 recomends +10db
|
||||
but due to horrible clipping when normalize
|
||||
is disabled we set this to 1.0
|
||||
*/
|
||||
{PCM_FRONT_LEFT , 1.0},//3.5},
|
||||
{PCM_FRONT_RIGHT , 1.0},//3.5},
|
||||
{PCM_INVALID}
|
||||
},
|
||||
/* PCM_BACK_LEFT */
|
||||
{
|
||||
{PCM_FRONT_LEFT , 1.0},
|
||||
{PCM_INVALID}
|
||||
},
|
||||
/* PCM_BACK_RIGHT */
|
||||
{
|
||||
{PCM_FRONT_RIGHT , 1.0},
|
||||
{PCM_INVALID}
|
||||
},
|
||||
/* PCM_FRONT_LEFT_OF_CENTER */
|
||||
{
|
||||
{PCM_FRONT_LEFT , 1.0},
|
||||
{PCM_FRONT_CENTER , 1.0, true},
|
||||
{PCM_INVALID}
|
||||
},
|
||||
/* PCM_FRONT_RIGHT_OF_CENTER */
|
||||
{
|
||||
{PCM_FRONT_RIGHT , 1.0},
|
||||
{PCM_FRONT_CENTER , 1.0, true},
|
||||
{PCM_INVALID}
|
||||
},
|
||||
/* PCM_BACK_CENTER */
|
||||
{
|
||||
{PCM_BACK_LEFT , 1.0},
|
||||
{PCM_BACK_RIGHT , 1.0},
|
||||
{PCM_INVALID}
|
||||
},
|
||||
/* PCM_SIDE_LEFT */
|
||||
{
|
||||
{PCM_FRONT_LEFT , 1.0},
|
||||
{PCM_BACK_LEFT , 1.0},
|
||||
{PCM_INVALID}
|
||||
},
|
||||
/* PCM_SIDE_RIGHT */
|
||||
{
|
||||
{PCM_FRONT_RIGHT , 1.0},
|
||||
{PCM_BACK_RIGHT , 1.0},
|
||||
{PCM_INVALID}
|
||||
},
|
||||
/* PCM_TOP_FRONT_LEFT */
|
||||
{
|
||||
{PCM_FRONT_LEFT , 1.0},
|
||||
{PCM_INVALID}
|
||||
},
|
||||
/* PCM_TOP_FRONT_RIGHT */
|
||||
{
|
||||
{PCM_FRONT_RIGHT , 1.0},
|
||||
{PCM_INVALID}
|
||||
},
|
||||
/* PCM_TOP_FRONT_CENTER */
|
||||
{
|
||||
{PCM_TOP_FRONT_LEFT , 1.0},
|
||||
{PCM_TOP_FRONT_RIGHT , 1.0},
|
||||
{PCM_INVALID}
|
||||
},
|
||||
/* PCM_TOP_CENTER */
|
||||
{
|
||||
{PCM_TOP_FRONT_LEFT , 1.0},
|
||||
{PCM_TOP_FRONT_RIGHT , 1.0},
|
||||
{PCM_INVALID}
|
||||
},
|
||||
/* PCM_TOP_BACK_LEFT */
|
||||
{
|
||||
{PCM_BACK_LEFT , 1.0},
|
||||
{PCM_INVALID}
|
||||
},
|
||||
/* PCM_TOP_BACK_RIGHT */
|
||||
{
|
||||
{PCM_BACK_RIGHT , 1.0},
|
||||
{PCM_INVALID}
|
||||
},
|
||||
/* PCM_TOP_BACK_CENTER */
|
||||
{
|
||||
{PCM_TOP_BACK_LEFT , 1.0},
|
||||
{PCM_TOP_BACK_RIGHT , 1.0},
|
||||
{PCM_INVALID}
|
||||
}
|
||||
};
|
||||
|
||||
CPCMRemap::CPCMRemap() :
|
||||
m_inSet (false),
|
||||
m_outSet (false),
|
||||
m_inChannels (0),
|
||||
m_outChannels (0),
|
||||
m_inSampleSize(0),
|
||||
m_ignoreLayout(false),
|
||||
m_buf(NULL),
|
||||
m_bufsize(0),
|
||||
m_attenuation (1.0),
|
||||
m_attenuationInc(0.0),
|
||||
m_attenuationMin(1.0),
|
||||
m_sampleRate (48000.0), //safe default
|
||||
m_holdCounter (0),
|
||||
m_limiterEnabled(false)
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
CPCMRemap::~CPCMRemap()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
void CPCMRemap::Dispose()
|
||||
{
|
||||
free(m_buf);
|
||||
m_buf = NULL;
|
||||
m_bufsize = 0;
|
||||
}
|
||||
|
||||
/* resolves the channels recursively and returns the new index of tablePtr */
|
||||
struct PCMMapInfo* CPCMRemap::ResolveChannel(enum PCMChannels channel, float level, bool ifExists, std::vector<enum PCMChannels> path, struct PCMMapInfo *tablePtr)
|
||||
{
|
||||
if (channel == PCM_INVALID) return tablePtr;
|
||||
|
||||
/* if its a 1 to 1 mapping, return */
|
||||
if (m_useable[channel])
|
||||
{
|
||||
tablePtr->channel = channel;
|
||||
tablePtr->level = level;
|
||||
|
||||
++tablePtr;
|
||||
tablePtr->channel = PCM_INVALID;
|
||||
return tablePtr;
|
||||
} else
|
||||
if (ifExists)
|
||||
level /= 2;
|
||||
|
||||
struct PCMMapInfo *info;
|
||||
std::vector<enum PCMChannels>::iterator itt;
|
||||
|
||||
for(info = PCMDownmixTable[channel]; info->channel != PCM_INVALID; ++info)
|
||||
{
|
||||
/* make sure we are not about to recurse into ourself */
|
||||
bool found = false;
|
||||
for(itt = path.begin(); itt != path.end(); ++itt)
|
||||
if (*itt == info->channel)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (found)
|
||||
continue;
|
||||
|
||||
path.push_back(channel);
|
||||
float l = (info->level * (level / 100)) * 100;
|
||||
tablePtr = ResolveChannel(info->channel, l, info->ifExists, path, tablePtr);
|
||||
path.pop_back();
|
||||
}
|
||||
|
||||
return tablePtr;
|
||||
}
|
||||
|
||||
/*
|
||||
Builds a lookup table without extra adjustments, useful if we simply
|
||||
want to find out which channels are active.
|
||||
For final adjustments, BuildMap() is used.
|
||||
*/
|
||||
void CPCMRemap::ResolveChannels()
|
||||
{
|
||||
unsigned int in_ch, out_ch;
|
||||
bool hasSide = false;
|
||||
bool hasBack = false;
|
||||
|
||||
memset(m_useable, 0, sizeof(m_useable));
|
||||
|
||||
if (!m_outSet)
|
||||
{
|
||||
/* Output format is not known yet, assume the full configured map.
|
||||
* Note that m_ignoreLayout-using callers normally ignore the result of
|
||||
* this function when !m_outSet, when it is called only for an advice for
|
||||
* the caller of SetInputFormat about the best possible output map, and
|
||||
* they can still set their output format arbitrarily in their call to
|
||||
* SetOutputFormat. */
|
||||
for (enum PCMChannels *chan = PCMLayoutMap[m_channelLayout]; *chan != PCM_INVALID; ++chan)
|
||||
m_useable[*chan] = true;
|
||||
}
|
||||
else if (m_ignoreLayout)
|
||||
{
|
||||
for(out_ch = 0; out_ch < m_outChannels; ++out_ch)
|
||||
m_useable[m_outMap[out_ch]] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* figure out what channels we have and can use */
|
||||
for(enum PCMChannels *chan = PCMLayoutMap[m_channelLayout]; *chan != PCM_INVALID; ++chan)
|
||||
{
|
||||
for(out_ch = 0; out_ch < m_outChannels; ++out_ch)
|
||||
if (m_outMap[out_ch] == *chan)
|
||||
{
|
||||
m_useable[*chan] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* force mono audio to front left and front right */
|
||||
if (!m_ignoreLayout && m_inChannels == 1 && m_inMap[0] == PCM_FRONT_CENTER
|
||||
&& m_useable[PCM_FRONT_LEFT] && m_useable[PCM_FRONT_RIGHT])
|
||||
{
|
||||
CLog::Log(LOGDEBUG, "CPCMRemap: Mapping mono audio to front left and front right");
|
||||
m_useable[PCM_FRONT_CENTER] = false;
|
||||
m_useable[PCM_FRONT_LEFT_OF_CENTER] = false;
|
||||
m_useable[PCM_FRONT_RIGHT_OF_CENTER] = false;
|
||||
}
|
||||
|
||||
/* see if our input has side/back channels */
|
||||
for(in_ch = 0; in_ch < m_inChannels; ++in_ch)
|
||||
switch(m_inMap[in_ch])
|
||||
{
|
||||
case PCM_SIDE_LEFT:
|
||||
case PCM_SIDE_RIGHT:
|
||||
hasSide = true;
|
||||
break;
|
||||
|
||||
case PCM_BACK_LEFT:
|
||||
case PCM_BACK_RIGHT:
|
||||
hasBack = true;
|
||||
break;
|
||||
|
||||
default:;
|
||||
}
|
||||
|
||||
/* if our input has side, and not back channels, and our output doesnt have side channels */
|
||||
if (hasSide && !hasBack && (!m_useable[PCM_SIDE_LEFT] || !m_useable[PCM_SIDE_RIGHT]))
|
||||
{
|
||||
CLog::Log(LOGDEBUG, "CPCMRemap: Forcing side channel map to back channels");
|
||||
for(in_ch = 0; in_ch < m_inChannels; ++in_ch)
|
||||
if (m_inMap[in_ch] == PCM_SIDE_LEFT ) m_inMap[in_ch] = PCM_BACK_LEFT;
|
||||
else if (m_inMap[in_ch] == PCM_SIDE_RIGHT) m_inMap[in_ch] = PCM_BACK_RIGHT;
|
||||
}
|
||||
|
||||
/* resolve all the channels */
|
||||
struct PCMMapInfo table[PCM_MAX_CH + 1], *info, *dst;
|
||||
std::vector<enum PCMChannels> path;
|
||||
|
||||
for (int i = 0; i < PCM_MAX_CH + 1; i++)
|
||||
{
|
||||
for (int j = 0; j < PCM_MAX_CH + 1; j++)
|
||||
m_lookupMap[i][j].channel = PCM_INVALID;
|
||||
}
|
||||
|
||||
memset(m_counts, 0, sizeof(m_counts));
|
||||
for(in_ch = 0; in_ch < m_inChannels; ++in_ch) {
|
||||
|
||||
for (int i = 0; i < PCM_MAX_CH + 1; i++)
|
||||
table[i].channel = PCM_INVALID;
|
||||
|
||||
ResolveChannel(m_inMap[in_ch], 1.0f, false, path, table);
|
||||
for(info = table; info->channel != PCM_INVALID; ++info)
|
||||
{
|
||||
/* find the end of the table */
|
||||
for(dst = m_lookupMap[info->channel]; dst->channel != PCM_INVALID; ++dst);
|
||||
|
||||
/* append it to the table and set its input offset */
|
||||
dst->channel = m_inMap[in_ch];
|
||||
dst->in_offset = in_ch * 2;
|
||||
dst->level = info->level;
|
||||
m_counts[dst->channel]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
builds a lookup table to convert from the input mapping to the output
|
||||
mapping, this decreases the amount of work per sample to remap it.
|
||||
*/
|
||||
void CPCMRemap::BuildMap()
|
||||
{
|
||||
struct PCMMapInfo *dst;
|
||||
unsigned int out_ch;
|
||||
|
||||
if (!m_inSet || !m_outSet) return;
|
||||
|
||||
m_inStride = m_inSampleSize * m_inChannels ;
|
||||
m_outStride = m_inSampleSize * m_outChannels;
|
||||
|
||||
/* see if we need to normalize the levels */
|
||||
bool dontnormalize = 1;
|
||||
CLog::Log(LOGDEBUG, "CPCMRemap: Downmix normalization is %s", (dontnormalize ? "disabled" : "enabled"));
|
||||
|
||||
ResolveChannels();
|
||||
|
||||
/* convert the levels into RMS values */
|
||||
float loudest = 0.0;
|
||||
bool hasLoudest = false;
|
||||
|
||||
for(out_ch = 0; out_ch < m_outChannels; ++out_ch)
|
||||
{
|
||||
float scale = 0;
|
||||
int count = 0;
|
||||
for(dst = m_lookupMap[m_outMap[out_ch]]; dst->channel != PCM_INVALID; ++dst)
|
||||
{
|
||||
dst->copy = false;
|
||||
dst->level = dst->level / sqrt((float)m_counts[dst->channel]);
|
||||
scale += dst->level;
|
||||
++count;
|
||||
}
|
||||
|
||||
/* if there is only 1 channel to mix, and the level is 1.0, then just copy the channel */
|
||||
dst = m_lookupMap[m_outMap[out_ch]];
|
||||
if (count == 1 && dst->level > 0.99 && dst->level < 1.01)
|
||||
dst->copy = true;
|
||||
|
||||
/* normalize the levels if it is turned on */
|
||||
if (!dontnormalize)
|
||||
for(dst = m_lookupMap[m_outMap[out_ch]]; dst->channel != PCM_INVALID; ++dst)
|
||||
{
|
||||
dst->level /= scale;
|
||||
/* find the loudest output level we have that is not 1-1 */
|
||||
if (dst->level < 1.0 && loudest < dst->level)
|
||||
{
|
||||
loudest = dst->level;
|
||||
hasLoudest = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* adjust the channels that are too loud */
|
||||
for(out_ch = 0; out_ch < m_outChannels; ++out_ch)
|
||||
{
|
||||
CStdString s = "", f;
|
||||
for(dst = m_lookupMap[m_outMap[out_ch]]; dst->channel != PCM_INVALID; ++dst)
|
||||
{
|
||||
if (hasLoudest && dst->copy)
|
||||
{
|
||||
dst->level = loudest;
|
||||
dst->copy = false;
|
||||
}
|
||||
|
||||
f.Format("%s(%f%s) ", PCMChannelStr(dst->channel).c_str(), dst->level, dst->copy ? "*" : "");
|
||||
s += f;
|
||||
}
|
||||
CLog::Log(LOGDEBUG, "CPCMRemap: %s = %s\n", PCMChannelStr(m_outMap[out_ch]).c_str(), s.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void CPCMRemap::DumpMap(CStdString info, unsigned int channels, enum PCMChannels *channelMap)
|
||||
{
|
||||
if (channelMap == NULL)
|
||||
{
|
||||
CLog::Log(LOGINFO, "CPCMRemap: %s channel map: NULL", info.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
CStdString mapping;
|
||||
for(unsigned int i = 0; i < channels; ++i)
|
||||
mapping += ((i == 0) ? "" : ",") + PCMChannelStr(channelMap[i]);
|
||||
|
||||
CLog::Log(LOGINFO, "CPCMRemap: %s channel map: %s\n", info.c_str(), mapping.c_str());
|
||||
}
|
||||
|
||||
void CPCMRemap::Reset()
|
||||
{
|
||||
m_inSet = false;
|
||||
m_outSet = false;
|
||||
Dispose();
|
||||
}
|
||||
|
||||
/* sets the input format, and returns the requested channel layout */
|
||||
enum PCMChannels *CPCMRemap::SetInputFormat(unsigned int channels, enum PCMChannels *channelMap, unsigned int sampleSize, unsigned int sampleRate)
|
||||
{
|
||||
m_inChannels = channels;
|
||||
m_inSampleSize = sampleSize;
|
||||
m_sampleRate = sampleRate;
|
||||
m_inSet = channelMap != NULL;
|
||||
if (channelMap)
|
||||
memcpy(m_inMap, channelMap, sizeof(enum PCMChannels) * channels);
|
||||
|
||||
/* fix me later */
|
||||
assert(sampleSize == 2);
|
||||
|
||||
/* get the audio layout, and count the channels in it */
|
||||
m_channelLayout = PCM_LAYOUT_2_0;
|
||||
if (m_channelLayout >= PCM_MAX_LAYOUT) m_channelLayout = PCM_LAYOUT_2_0;
|
||||
|
||||
|
||||
DumpMap("I", channels, channelMap);
|
||||
BuildMap();
|
||||
|
||||
/* now remove the empty channels from PCMLayoutMap;
|
||||
* we don't perform upmixing so we want the minimum amount of those */
|
||||
if (channelMap) {
|
||||
if (!m_outSet)
|
||||
ResolveChannels(); /* Do basic channel resolving to find out the empty channels;
|
||||
* If m_outSet == true, this was done already by BuildMap() above */
|
||||
int i = 0;
|
||||
for (enum PCMChannels *chan = PCMLayoutMap[m_channelLayout]; *chan != PCM_INVALID; ++chan)
|
||||
if (m_lookupMap[*chan][0].channel != PCM_INVALID) {
|
||||
/* something is mapped here, so add the channel */
|
||||
m_layoutMap[i++] = *chan;
|
||||
}
|
||||
m_layoutMap[i] = PCM_INVALID;
|
||||
} else
|
||||
memcpy(m_layoutMap, PCMLayoutMap[m_channelLayout], sizeof(PCMLayoutMap[m_channelLayout]));
|
||||
|
||||
m_attenuation = 1.0;
|
||||
m_attenuationInc = 1.0;
|
||||
m_holdCounter = 0;
|
||||
|
||||
return m_layoutMap;
|
||||
}
|
||||
|
||||
/* sets the output format supported by the audio renderer */
|
||||
void CPCMRemap::SetOutputFormat(unsigned int channels, enum PCMChannels *channelMap, bool ignoreLayout/* = false */)
|
||||
{
|
||||
m_outChannels = channels;
|
||||
m_outSet = channelMap != NULL;
|
||||
m_ignoreLayout = ignoreLayout;
|
||||
if (channelMap)
|
||||
memcpy(m_outMap, channelMap, sizeof(enum PCMChannels) * channels);
|
||||
|
||||
DumpMap("O", channels, channelMap);
|
||||
BuildMap();
|
||||
|
||||
m_attenuation = 1.0;
|
||||
m_attenuationInc = 1.0;
|
||||
m_holdCounter = 0;
|
||||
}
|
||||
|
||||
void CPCMRemap::Remap(void *data, void *out, unsigned int samples, long drc)
|
||||
{
|
||||
float gain = 1.0f;
|
||||
if (drc > 0)
|
||||
gain = pow(10.0f, (float)drc / 1000.0f);
|
||||
|
||||
Remap(data, out, samples, gain);
|
||||
}
|
||||
|
||||
/* remap the supplied data into out, which must be pre-allocated */
|
||||
void CPCMRemap::Remap(void *data, void *out, unsigned int samples, float gain /*= 1.0f*/)
|
||||
{
|
||||
CheckBufferSize(samples * m_outChannels * sizeof(float));
|
||||
|
||||
//set output buffer to 0
|
||||
memset(out, 0, samples * m_outChannels * m_inSampleSize);
|
||||
|
||||
//set intermediate buffer to 0
|
||||
memset(m_buf, 0, m_bufsize);
|
||||
|
||||
ProcessInput(data, out, samples, gain);
|
||||
//AddGain(m_buf, samples * m_outChannels, gain);
|
||||
//ProcessLimiter(samples, gain);
|
||||
ProcessOutput(out, samples, gain);
|
||||
}
|
||||
|
||||
void CPCMRemap::CheckBufferSize(int size)
|
||||
{
|
||||
if (m_bufsize < size)
|
||||
{
|
||||
m_bufsize = size;
|
||||
m_buf = (float*)realloc(m_buf, m_bufsize);
|
||||
}
|
||||
}
|
||||
|
||||
void CPCMRemap::ProcessInput(void* data, void* out, unsigned int samples, float gain)
|
||||
{
|
||||
for (unsigned int ch = 0; ch < m_outChannels; ch++)
|
||||
{
|
||||
struct PCMMapInfo *info = m_lookupMap[m_outMap[ch]];
|
||||
if (info->channel == PCM_INVALID)
|
||||
continue;
|
||||
|
||||
if (info->copy && gain == 1.0f) //do direct copy
|
||||
{
|
||||
uint8_t* src = (uint8_t*)data + info->in_offset;
|
||||
uint8_t* dst = (uint8_t*)out + ch * m_inSampleSize;
|
||||
uint8_t* dstend = dst + samples * m_outStride;
|
||||
while (dst < dstend)
|
||||
{
|
||||
*(int16_t*)dst = *(int16_t*)src;
|
||||
src += m_inStride;
|
||||
dst += m_outStride;
|
||||
}
|
||||
}
|
||||
else //needs some volume change or mixing, put into intermediate buffer
|
||||
{
|
||||
for(; info->channel != PCM_INVALID; info++)
|
||||
{
|
||||
uint8_t* src = (uint8_t*)data + info->in_offset;
|
||||
float* dst = m_buf + ch;
|
||||
float* dstend = dst + samples * m_outChannels;
|
||||
while (dst < dstend)
|
||||
{
|
||||
*dst += (float)(*(int16_t*)src) * info->level;
|
||||
src += m_inStride;
|
||||
dst += m_outChannels;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CPCMRemap::AddGain(float* buf, unsigned int samples, float gain)
|
||||
{
|
||||
if (gain != 1.0f) //needs a gain change
|
||||
{
|
||||
float* ptr = m_buf;
|
||||
float* end = m_buf + samples;
|
||||
while (ptr < end)
|
||||
*(ptr++) *= gain;
|
||||
}
|
||||
}
|
||||
|
||||
void CPCMRemap::ProcessLimiter(unsigned int samples, float gain)
|
||||
{
|
||||
//check total gain for each output channel
|
||||
float highestgain = 1.0f;
|
||||
for (unsigned int ch = 0; ch < m_outChannels; ch++)
|
||||
{
|
||||
struct PCMMapInfo *info = m_lookupMap[m_outMap[ch]];
|
||||
if (info->channel == PCM_INVALID)
|
||||
continue;
|
||||
|
||||
float chgain = 0.0f;
|
||||
for(; info->channel != PCM_INVALID; info++)
|
||||
chgain += info->level * gain;
|
||||
|
||||
if (chgain > highestgain)
|
||||
highestgain = chgain;
|
||||
}
|
||||
|
||||
m_attenuationMin = 1.0f;
|
||||
|
||||
//if one of the channels can clip, enable a limiter
|
||||
if (highestgain > 1.0001f)
|
||||
{
|
||||
m_attenuationMin = m_attenuation;
|
||||
|
||||
if (!m_limiterEnabled)
|
||||
{
|
||||
CLog::Log(LOGDEBUG, "CPCMRemap:: max gain: %f, enabling limiter", highestgain);
|
||||
m_limiterEnabled = true;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < samples; i++)
|
||||
{
|
||||
//for each collection of samples, get the highest absolute value
|
||||
float maxAbs = 0.0f;
|
||||
for (unsigned int outch = 0; outch < m_outChannels; outch++)
|
||||
{
|
||||
float absval = fabs(m_buf[i * m_outChannels + outch]) / 32768.0f;
|
||||
if (maxAbs < absval)
|
||||
maxAbs = absval;
|
||||
}
|
||||
|
||||
//if attenuatedAbs is higher than 1.0f, audio is clipping
|
||||
float attenuatedAbs = maxAbs * m_attenuation;
|
||||
if (attenuatedAbs > 1.0f)
|
||||
{
|
||||
//set m_attenuation so that m_attenuation * sample is the maximum output value
|
||||
m_attenuation = 1.0f / maxAbs;
|
||||
if (m_attenuation < m_attenuationMin)
|
||||
m_attenuationMin = m_attenuation;
|
||||
//value to add to m_attenuation to make it 1.0f
|
||||
m_attenuationInc = 1.0f - m_attenuation;
|
||||
//amount of samples to hold m_attenuation
|
||||
m_holdCounter = MathUtils::round_int(m_sampleRate * 0.025f);
|
||||
}
|
||||
else if (m_attenuation < 1.0f && attenuatedAbs > 0.95f)
|
||||
{
|
||||
//if we're attenuating and we get within 5% of clipping, hold m_attenuation
|
||||
m_attenuationInc = 1.0f - m_attenuation;
|
||||
m_holdCounter = MathUtils::round_int(m_sampleRate * 0.025f);
|
||||
}
|
||||
|
||||
//apply attenuation
|
||||
for (unsigned int outch = 0; outch < m_outChannels; outch++)
|
||||
m_buf[i * m_outChannels + outch] *= m_attenuation;
|
||||
|
||||
if (m_holdCounter)
|
||||
{
|
||||
//hold m_attenuation
|
||||
m_holdCounter--;
|
||||
}
|
||||
else if (m_attenuationInc > 0.0f)
|
||||
{
|
||||
//move m_attenuation to 1.0 in g_advancedSettings.m_limiterRelease seconds
|
||||
m_attenuation += m_attenuationInc / m_sampleRate / 0.1f;
|
||||
if (m_attenuation > 1.0f)
|
||||
{
|
||||
m_attenuation = 1.0f;
|
||||
m_attenuationInc = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_limiterEnabled)
|
||||
{
|
||||
CLog::Log(LOGDEBUG, "CPCMRemap:: max gain: %f, disabling limiter", highestgain);
|
||||
m_limiterEnabled = false;
|
||||
}
|
||||
|
||||
//reset the limiter
|
||||
m_attenuation = 1.0f;
|
||||
m_attenuationInc = 0.0f;
|
||||
m_holdCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CPCMRemap::ProcessOutput(void* out, unsigned int samples, float gain)
|
||||
{
|
||||
//copy from intermediate buffer to output
|
||||
for (unsigned int ch = 0; ch < m_outChannels; ch++)
|
||||
{
|
||||
struct PCMMapInfo *info = m_lookupMap[m_outMap[ch]];
|
||||
if (info->channel == PCM_INVALID)
|
||||
continue;
|
||||
|
||||
if (!info->copy || gain != 1.0f)
|
||||
{
|
||||
float* src = m_buf + ch;
|
||||
uint8_t* dst = (uint8_t*)out + ch * m_inSampleSize;
|
||||
uint8_t* dstend = dst + samples * m_outStride;
|
||||
|
||||
while(dst < dstend)
|
||||
{
|
||||
*(int16_t*)dst = MathUtils::round_int(std::min(std::max(*src, (float)INT16_MIN), (float)INT16_MAX));
|
||||
src += m_outChannels;
|
||||
dst += m_outStride;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CPCMRemap::CanRemap()
|
||||
{
|
||||
return (m_inSet && m_outSet);
|
||||
}
|
||||
|
||||
int CPCMRemap::InBytesToFrames(int bytes)
|
||||
{
|
||||
return bytes / m_inSampleSize / m_inChannels;
|
||||
}
|
||||
|
||||
int CPCMRemap::FramesToOutBytes(int frames)
|
||||
{
|
||||
return frames * m_inSampleSize * m_outChannels;
|
||||
}
|
||||
|
||||
int CPCMRemap::FramesToInBytes(int frames)
|
||||
{
|
||||
return frames * m_inSampleSize * m_inChannels;
|
||||
}
|
||||
|
||||
CStdString CPCMRemap::PCMChannelStr(enum PCMChannels ename)
|
||||
{
|
||||
const char* PCMChannelName[] =
|
||||
{
|
||||
"FL",
|
||||
"FR",
|
||||
"CE",
|
||||
"LFE",
|
||||
"BL",
|
||||
"BR",
|
||||
"FLOC",
|
||||
"FROC",
|
||||
"BC",
|
||||
"SL",
|
||||
"SR",
|
||||
"TFL",
|
||||
"TFR",
|
||||
"TFC",
|
||||
"TC",
|
||||
"TBL",
|
||||
"TBR",
|
||||
"TBC"
|
||||
};
|
||||
|
||||
int namepos = (int)ename;
|
||||
CStdString namestr;
|
||||
|
||||
if (namepos < 0 || namepos >= (int)(sizeof(PCMChannelName) / sizeof(const char*)))
|
||||
namestr.Format("UNKNOWN CHANNEL:%i", namepos);
|
||||
else
|
||||
namestr = PCMChannelName[namepos];
|
||||
|
||||
return namestr;
|
||||
}
|
||||
|
||||
CStdString CPCMRemap::PCMLayoutStr(enum PCMLayout ename)
|
||||
{
|
||||
const char* PCMLayoutName[] =
|
||||
{
|
||||
"2.0",
|
||||
"2.1",
|
||||
"3.0",
|
||||
"3.1",
|
||||
"4.0",
|
||||
"4.1",
|
||||
"5.0",
|
||||
"5.1",
|
||||
"7.0",
|
||||
"7.1"
|
||||
};
|
||||
|
||||
int namepos = (int)ename;
|
||||
CStdString namestr;
|
||||
|
||||
if (namepos < 0 || namepos >= (int)(sizeof(PCMLayoutName) / sizeof(const char*)))
|
||||
namestr.Format("UNKNOWN LAYOUT:%i", namepos);
|
||||
else
|
||||
namestr = PCMLayoutName[namepos];
|
||||
|
||||
return namestr;
|
||||
}
|
||||
|
||||
147
utils/PCMRemap.h
Normal file
147
utils/PCMRemap.h
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
#ifndef __PCM_REMAP__H__
|
||||
#define __PCM_REMAP__H__
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include "StdString.h"
|
||||
|
||||
#define PCM_MAX_CH 18
|
||||
enum PCMChannels
|
||||
{
|
||||
PCM_INVALID = -1,
|
||||
PCM_FRONT_LEFT,
|
||||
PCM_FRONT_RIGHT,
|
||||
PCM_FRONT_CENTER,
|
||||
PCM_LOW_FREQUENCY,
|
||||
PCM_BACK_LEFT,
|
||||
PCM_BACK_RIGHT,
|
||||
PCM_FRONT_LEFT_OF_CENTER,
|
||||
PCM_FRONT_RIGHT_OF_CENTER,
|
||||
PCM_BACK_CENTER,
|
||||
PCM_SIDE_LEFT,
|
||||
PCM_SIDE_RIGHT,
|
||||
PCM_TOP_FRONT_LEFT,
|
||||
PCM_TOP_FRONT_RIGHT,
|
||||
PCM_TOP_FRONT_CENTER,
|
||||
PCM_TOP_CENTER,
|
||||
PCM_TOP_BACK_LEFT,
|
||||
PCM_TOP_BACK_RIGHT,
|
||||
PCM_TOP_BACK_CENTER
|
||||
};
|
||||
|
||||
#define PCM_MAX_LAYOUT 10
|
||||
enum PCMLayout
|
||||
{
|
||||
PCM_LAYOUT_2_0 = 0,
|
||||
PCM_LAYOUT_2_1,
|
||||
PCM_LAYOUT_3_0,
|
||||
PCM_LAYOUT_3_1,
|
||||
PCM_LAYOUT_4_0,
|
||||
PCM_LAYOUT_4_1,
|
||||
PCM_LAYOUT_5_0,
|
||||
PCM_LAYOUT_5_1,
|
||||
PCM_LAYOUT_7_0,
|
||||
PCM_LAYOUT_7_1
|
||||
};
|
||||
|
||||
struct PCMMapInfo
|
||||
{
|
||||
enum PCMChannels channel;
|
||||
float level;
|
||||
bool ifExists;
|
||||
int in_offset;
|
||||
bool copy;
|
||||
};
|
||||
|
||||
//! Channels remapper class
|
||||
/*!
|
||||
The usual set-up process:
|
||||
- user calls SetInputFormat with the input channels information
|
||||
- SetInputFormat responds with a channelmap corresponding to the speaker
|
||||
layout that the user has configured, with empty (according to information
|
||||
calculated from the input channelmap) channels removed
|
||||
- user uses this information to create the desired output channelmap,
|
||||
and calls SetOutputFormat to set it (if the channelmap contains channels
|
||||
that do not exist in the configured speaker layout, they will contain
|
||||
only silence unless ignoreLayout is true)
|
||||
*/
|
||||
|
||||
class CPCMRemap
|
||||
{
|
||||
protected:
|
||||
bool m_inSet, m_outSet;
|
||||
enum PCMLayout m_channelLayout;
|
||||
unsigned int m_inChannels, m_outChannels;
|
||||
unsigned int m_inSampleSize;
|
||||
enum PCMChannels m_inMap [PCM_MAX_CH];
|
||||
enum PCMChannels m_outMap[PCM_MAX_CH];
|
||||
enum PCMChannels m_layoutMap[PCM_MAX_CH + 1];
|
||||
|
||||
bool m_ignoreLayout;
|
||||
bool m_useable [PCM_MAX_CH];
|
||||
int m_inStride, m_outStride;
|
||||
struct PCMMapInfo m_lookupMap[PCM_MAX_CH + 1][PCM_MAX_CH + 1];
|
||||
int m_counts[PCM_MAX_CH];
|
||||
|
||||
float* m_buf;
|
||||
int m_bufsize;
|
||||
float m_attenuation;
|
||||
float m_attenuationInc;
|
||||
float m_attenuationMin; //lowest attenuation value during a call of Remap(), used for the codec info
|
||||
float m_sampleRate;
|
||||
unsigned int m_holdCounter;
|
||||
bool m_limiterEnabled;
|
||||
|
||||
struct PCMMapInfo* ResolveChannel(enum PCMChannels channel, float level, bool ifExists, std::vector<enum PCMChannels> path, struct PCMMapInfo *tablePtr);
|
||||
void ResolveChannels(); //!< Partial BuildMap(), just enough to see which output channels are active
|
||||
void BuildMap();
|
||||
void DumpMap(CStdString info, int unsigned channels, enum PCMChannels *channelMap);
|
||||
void Dispose();
|
||||
CStdString PCMChannelStr(enum PCMChannels ename);
|
||||
CStdString PCMLayoutStr(enum PCMLayout ename);
|
||||
|
||||
void CheckBufferSize(int size);
|
||||
void ProcessInput(void* data, void* out, unsigned int samples, float gain);
|
||||
void AddGain(float* buf, unsigned int samples, float gain);
|
||||
void ProcessLimiter(unsigned int samples, float gain);
|
||||
void ProcessOutput(void* out, unsigned int samples, float gain);
|
||||
|
||||
public:
|
||||
|
||||
CPCMRemap();
|
||||
~CPCMRemap();
|
||||
|
||||
void Reset();
|
||||
enum PCMChannels *SetInputFormat (unsigned int channels, enum PCMChannels *channelMap, unsigned int sampleSize, unsigned int sampleRate);
|
||||
void SetOutputFormat(unsigned int channels, enum PCMChannels *channelMap, bool ignoreLayout = false);
|
||||
void Remap(void *data, void *out, unsigned int samples, long drc);
|
||||
void Remap(void *data, void *out, unsigned int samples, float gain = 1.0f);
|
||||
bool CanRemap();
|
||||
int InBytesToFrames (int bytes );
|
||||
int FramesToOutBytes(int frames);
|
||||
int FramesToInBytes (int frames);
|
||||
float GetCurrentAttenuation() { return m_attenuationMin; }
|
||||
};
|
||||
|
||||
#endif
|
||||
266
utils/RegExp.cpp
Normal file
266
utils/RegExp.cpp
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "RegExp.h"
|
||||
#include "StdString.h"
|
||||
#include "log.h"
|
||||
|
||||
using namespace PCRE;
|
||||
|
||||
CRegExp::CRegExp(bool caseless)
|
||||
{
|
||||
m_re = NULL;
|
||||
m_iOptions = PCRE_DOTALL;
|
||||
if(caseless)
|
||||
m_iOptions |= PCRE_CASELESS;
|
||||
|
||||
m_bMatched = false;
|
||||
m_iMatchCount = 0;
|
||||
}
|
||||
|
||||
CRegExp::CRegExp(const CRegExp& re)
|
||||
{
|
||||
m_re = NULL;
|
||||
m_iOptions = re.m_iOptions;
|
||||
*this = re;
|
||||
}
|
||||
|
||||
const CRegExp& CRegExp::operator=(const CRegExp& re)
|
||||
{
|
||||
size_t size;
|
||||
Cleanup();
|
||||
m_pattern = re.m_pattern;
|
||||
if (re.m_re)
|
||||
{
|
||||
if (pcre_fullinfo(re.m_re, NULL, PCRE_INFO_SIZE, &size) >= 0)
|
||||
{
|
||||
if ((m_re = (pcre*)malloc(size)))
|
||||
{
|
||||
memcpy(m_re, re.m_re, size);
|
||||
memcpy(m_iOvector, re.m_iOvector, OVECCOUNT*sizeof(int));
|
||||
m_iMatchCount = re.m_iMatchCount;
|
||||
m_bMatched = re.m_bMatched;
|
||||
m_subject = re.m_subject;
|
||||
m_iOptions = re.m_iOptions;
|
||||
}
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegExp::~CRegExp()
|
||||
{
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
CRegExp* CRegExp::RegComp(const char *re)
|
||||
{
|
||||
if (!re)
|
||||
return NULL;
|
||||
|
||||
m_bMatched = false;
|
||||
m_iMatchCount = 0;
|
||||
const char *errMsg = NULL;
|
||||
int errOffset = 0;
|
||||
|
||||
Cleanup();
|
||||
|
||||
m_re = pcre_compile(re, m_iOptions, &errMsg, &errOffset, NULL);
|
||||
if (!m_re)
|
||||
{
|
||||
m_pattern.clear();
|
||||
CLog::Log(LOGERROR, "PCRE: %s. Compilation failed at offset %d in expression '%s'",
|
||||
errMsg, errOffset, re);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m_pattern = re;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
int CRegExp::RegFind(const char* str, int startoffset)
|
||||
{
|
||||
m_bMatched = false;
|
||||
m_iMatchCount = 0;
|
||||
|
||||
if (!m_re)
|
||||
{
|
||||
CLog::Log(LOGERROR, "PCRE: Called before compilation");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!str)
|
||||
{
|
||||
CLog::Log(LOGERROR, "PCRE: Called without a string to match");
|
||||
return -1;
|
||||
}
|
||||
|
||||
m_subject = str;
|
||||
int rc = pcre_exec(m_re, NULL, str, strlen(str), startoffset, 0, m_iOvector, OVECCOUNT);
|
||||
|
||||
if (rc<1)
|
||||
{
|
||||
switch(rc)
|
||||
{
|
||||
case PCRE_ERROR_NOMATCH:
|
||||
return -1;
|
||||
|
||||
case PCRE_ERROR_MATCHLIMIT:
|
||||
CLog::Log(LOGERROR, "PCRE: Match limit reached");
|
||||
return -1;
|
||||
|
||||
default:
|
||||
CLog::Log(LOGERROR, "PCRE: Unknown error: %d", rc);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
m_bMatched = true;
|
||||
m_iMatchCount = rc;
|
||||
return m_iOvector[0];
|
||||
}
|
||||
|
||||
int CRegExp::GetCaptureTotal()
|
||||
{
|
||||
int c = -1;
|
||||
if (m_re)
|
||||
pcre_fullinfo(m_re, NULL, PCRE_INFO_CAPTURECOUNT, &c);
|
||||
return c;
|
||||
}
|
||||
|
||||
char* CRegExp::GetReplaceString( const char* sReplaceExp )
|
||||
{
|
||||
char *src = (char *)sReplaceExp;
|
||||
char *buf;
|
||||
char c;
|
||||
int no;
|
||||
size_t len;
|
||||
|
||||
if( sReplaceExp == NULL || !m_bMatched )
|
||||
return NULL;
|
||||
|
||||
|
||||
// First compute the length of the string
|
||||
int replacelen = 0;
|
||||
while ((c = *src++) != '\0')
|
||||
{
|
||||
if (c == '&')
|
||||
no = 0;
|
||||
else if (c == '\\' && isdigit(*src))
|
||||
no = *src++ - '0';
|
||||
else
|
||||
no = -1;
|
||||
|
||||
if (no < 0)
|
||||
{
|
||||
// Ordinary character.
|
||||
if (c == '\\' && (*src == '\\' || *src == '&'))
|
||||
c = *src++;
|
||||
replacelen++;
|
||||
}
|
||||
else if (no < m_iMatchCount && (m_iOvector[no*2]>=0))
|
||||
{
|
||||
// Get tagged expression
|
||||
len = m_iOvector[no*2+1] - m_iOvector[no*2];
|
||||
replacelen += len;
|
||||
}
|
||||
}
|
||||
|
||||
// Now allocate buf
|
||||
buf = (char *)malloc((replacelen + 1)*sizeof(char));
|
||||
if( buf == NULL )
|
||||
return NULL;
|
||||
|
||||
char* sReplaceStr = buf;
|
||||
|
||||
// Add null termination
|
||||
buf[replacelen] = '\0';
|
||||
|
||||
// Now we can create the string
|
||||
src = (char *)sReplaceExp;
|
||||
while ((c = *src++) != '\0')
|
||||
{
|
||||
if (c == '&')
|
||||
no = 0;
|
||||
else if (c == '\\' && isdigit(*src))
|
||||
no = *src++ - '0';
|
||||
else
|
||||
no = -1;
|
||||
|
||||
if (no < 0)
|
||||
{
|
||||
// Ordinary character.
|
||||
if (c == '\\' && (*src == '\\' || *src == '&'))
|
||||
c = *src++;
|
||||
*buf++ = c;
|
||||
}
|
||||
else if (no < m_iMatchCount && (m_iOvector[no*2]>=0))
|
||||
{
|
||||
// Get tagged expression
|
||||
len = m_iOvector[no*2+1] - m_iOvector[no*2];
|
||||
strncpy(buf, m_subject.c_str()+m_iOvector[no*2], len);
|
||||
buf += len;
|
||||
}
|
||||
}
|
||||
|
||||
return sReplaceStr;
|
||||
}
|
||||
|
||||
std::string CRegExp::GetMatch(int iSub /* = 0 */)
|
||||
{
|
||||
if (iSub < 0 || iSub > m_iMatchCount)
|
||||
return "";
|
||||
|
||||
int pos = m_iOvector[(iSub*2)];
|
||||
int len = m_iOvector[(iSub*2)+1] - pos;
|
||||
return m_subject.substr(pos, len);
|
||||
}
|
||||
|
||||
bool CRegExp::GetNamedSubPattern(const char* strName, std::string& strMatch)
|
||||
{
|
||||
strMatch.clear();
|
||||
int iSub = pcre_get_stringnumber(m_re, strName);
|
||||
if (iSub < 0)
|
||||
return false;
|
||||
strMatch = GetMatch(iSub);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CRegExp::DumpOvector(int iLog /* = LOGDEBUG */)
|
||||
{
|
||||
if (iLog < LOGDEBUG || iLog > LOGNONE)
|
||||
return;
|
||||
|
||||
CStdString str = "{";
|
||||
int size = GetSubCount(); // past the subpatterns is junk
|
||||
for (int i = 0; i <= size; i++)
|
||||
{
|
||||
CStdString t;
|
||||
t.Format("[%i,%i]", m_iOvector[(i*2)], m_iOvector[(i*2)+1]);
|
||||
if (i != size)
|
||||
t += ",";
|
||||
str += t;
|
||||
}
|
||||
str += "}";
|
||||
CLog::Log(iLog, "regexp ovector=%s", str.c_str());
|
||||
}
|
||||
87
utils/RegExp.h
Normal file
87
utils/RegExp.h
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
#pragma once
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef REGEXP_H
|
||||
#define REGEXP_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace PCRE {
|
||||
#ifdef _WIN32
|
||||
#define PCRE_STATIC
|
||||
#include "lib/win32/pcre/pcre.h"
|
||||
#else
|
||||
#include <pcre.h>
|
||||
#endif
|
||||
}
|
||||
|
||||
// maximum of 20 backreferences
|
||||
// OVEVCOUNT must be a multiple of 3
|
||||
const int OVECCOUNT=(20+1)*3;
|
||||
|
||||
class CRegExp
|
||||
{
|
||||
public:
|
||||
CRegExp(bool caseless = false);
|
||||
CRegExp(const CRegExp& re);
|
||||
~CRegExp();
|
||||
|
||||
CRegExp* RegComp(const char *re);
|
||||
CRegExp* RegComp(const std::string& re) { return RegComp(re.c_str()); }
|
||||
int RegFind(const char *str, int startoffset = 0);
|
||||
int RegFind(const std::string& str, int startoffset = 0) { return RegFind(str.c_str(), startoffset); }
|
||||
char* GetReplaceString( const char* sReplaceExp );
|
||||
int GetFindLen()
|
||||
{
|
||||
if (!m_re || !m_bMatched)
|
||||
return 0;
|
||||
|
||||
return (m_iOvector[1] - m_iOvector[0]);
|
||||
};
|
||||
int GetSubCount() { return m_iMatchCount - 1; } // PCRE returns the number of sub-patterns + 1
|
||||
int GetSubStart(int iSub) { return m_iOvector[iSub*2]; } // normalized to match old engine
|
||||
int GetSubLength(int iSub) { return (m_iOvector[(iSub*2)+1] - m_iOvector[(iSub*2)]); } // correct spelling
|
||||
int GetCaptureTotal();
|
||||
std::string GetMatch(int iSub = 0);
|
||||
const std::string& GetPattern() { return m_pattern; }
|
||||
bool GetNamedSubPattern(const char* strName, std::string& strMatch);
|
||||
void DumpOvector(int iLog);
|
||||
const CRegExp& operator= (const CRegExp& re);
|
||||
|
||||
private:
|
||||
void Cleanup() { if (m_re) { PCRE::pcre_free(m_re); m_re = NULL; } }
|
||||
|
||||
private:
|
||||
PCRE::pcre* m_re;
|
||||
int m_iOvector[OVECCOUNT];
|
||||
int m_iMatchCount;
|
||||
int m_iOptions;
|
||||
bool m_bMatched;
|
||||
std::string m_subject;
|
||||
std::string m_pattern;
|
||||
};
|
||||
|
||||
typedef std::vector<CRegExp> VECCREGEXP;
|
||||
|
||||
#endif
|
||||
|
||||
4344
utils/StdString.h
Normal file
4344
utils/StdString.h
Normal file
File diff suppressed because it is too large
Load diff
220
utils/log.cpp
Normal file
220
utils/log.cpp
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
#include "log.h"
|
||||
#include "stdio_utf8.h"
|
||||
#include "stat_utf8.h"
|
||||
#include "utils/StdString.h"
|
||||
|
||||
static FILE* m_file = NULL;
|
||||
static int m_repeatCount = 0;
|
||||
static int m_repeatLogLevel = -1;
|
||||
static std::string m_repeatLine = "";
|
||||
static int m_logLevel = LOG_LEVEL_DEBUG;
|
||||
|
||||
static pthread_mutex_t m_log_mutex;
|
||||
|
||||
static char levelNames[][8] =
|
||||
{"DEBUG", "INFO", "NOTICE", "WARNING", "ERROR", "SEVERE", "FATAL", "NONE"};
|
||||
|
||||
CLog::CLog()
|
||||
{}
|
||||
|
||||
CLog::~CLog()
|
||||
{}
|
||||
|
||||
void CLog::Close()
|
||||
{
|
||||
if (m_file)
|
||||
{
|
||||
fclose(m_file);
|
||||
m_file = NULL;
|
||||
}
|
||||
m_repeatLine.clear();
|
||||
pthread_mutex_destroy(&m_log_mutex);
|
||||
}
|
||||
|
||||
void CLog::Log(int loglevel, const char *format, ... )
|
||||
{
|
||||
pthread_mutex_lock(&m_log_mutex);
|
||||
|
||||
static const char* prefixFormat = "%02.2d:%02.2d:%02.2d T:%"PRIu64" %7s: ";
|
||||
#if !(defined(_DEBUG) || defined(PROFILE))
|
||||
if (m_logLevel > LOG_LEVEL_NORMAL ||
|
||||
(m_logLevel > LOG_LEVEL_NONE && loglevel >= LOGNOTICE))
|
||||
#endif
|
||||
{
|
||||
if (!m_file)
|
||||
{
|
||||
pthread_mutex_unlock(&m_log_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
SYSTEMTIME time;
|
||||
//GetLocalTime(&time);
|
||||
|
||||
CStdString strPrefix, strData;
|
||||
|
||||
strData.reserve(16384);
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
strData.FormatV(format,va);
|
||||
va_end(va);
|
||||
|
||||
if (m_repeatLogLevel == loglevel && m_repeatLine == strData)
|
||||
{
|
||||
m_repeatCount++;
|
||||
pthread_mutex_unlock(&m_log_mutex);
|
||||
return;
|
||||
}
|
||||
else if (m_repeatCount)
|
||||
{
|
||||
CStdString strData2;
|
||||
time.wHour = 0;
|
||||
time.wMinute = 0;
|
||||
time.wSecond = 0;
|
||||
strPrefix.Format(prefixFormat, time.wHour, time.wMinute, time.wSecond, (uint64_t)0, levelNames[m_repeatLogLevel]);
|
||||
|
||||
strData2.Format("Previous line repeats %d times." LINE_ENDING, m_repeatCount);
|
||||
fputs(strPrefix.c_str(), m_file);
|
||||
fputs(strData2.c_str(), m_file);
|
||||
OutputDebugString(strData2);
|
||||
m_repeatCount = 0;
|
||||
}
|
||||
|
||||
m_repeatLine = strData;
|
||||
m_repeatLogLevel = loglevel;
|
||||
|
||||
unsigned int length = 0;
|
||||
while ( length != strData.length() )
|
||||
{
|
||||
length = strData.length();
|
||||
strData.TrimRight(" ");
|
||||
strData.TrimRight('\n');
|
||||
strData.TrimRight("\r");
|
||||
}
|
||||
|
||||
if (!length)
|
||||
{
|
||||
pthread_mutex_unlock(&m_log_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
OutputDebugString(strData);
|
||||
|
||||
/* fixup newline alignment, number of spaces should equal prefix length */
|
||||
strData.Replace("\n", LINE_ENDING" ");
|
||||
strData += LINE_ENDING;
|
||||
|
||||
strPrefix.Format(prefixFormat, time.wHour, time.wMinute, time.wSecond, (uint64_t)0, levelNames[loglevel]);
|
||||
|
||||
fputs(strPrefix.c_str(), m_file);
|
||||
fputs(strData.c_str(), m_file);
|
||||
//fputs(strPrefix.c_str(), stdout);
|
||||
//fputs(strData.c_str(), stdout);
|
||||
fflush(m_file);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&m_log_mutex);
|
||||
}
|
||||
|
||||
bool CLog::Init(const char* path)
|
||||
{
|
||||
pthread_mutex_init(&m_log_mutex, NULL);
|
||||
if (!m_file)
|
||||
{
|
||||
CStdString strLogFile, strLogFileOld;
|
||||
|
||||
strLogFile.Format("omxplayer.log", path);
|
||||
strLogFileOld.Format("omxplayer.old.log", path);
|
||||
|
||||
struct stat info;
|
||||
if (stat(strLogFileOld.c_str(),&info) == 0 &&
|
||||
remove(strLogFileOld.c_str()) != 0)
|
||||
return false;
|
||||
if (stat(strLogFile.c_str(),&info) == 0 &&
|
||||
rename(strLogFile.c_str(),strLogFileOld.c_str()) != 0)
|
||||
return false;
|
||||
|
||||
m_file = fopen(strLogFile.c_str(),"wb");
|
||||
}
|
||||
|
||||
if (m_file)
|
||||
{
|
||||
unsigned char BOM[3] = {0xEF, 0xBB, 0xBF};
|
||||
fwrite(BOM, sizeof(BOM), 1, m_file);
|
||||
}
|
||||
|
||||
return m_file != NULL;
|
||||
}
|
||||
|
||||
void CLog::MemDump(char *pData, int length)
|
||||
{
|
||||
Log(LOGDEBUG, "MEM_DUMP: Dumping from %p", pData);
|
||||
for (int i = 0; i < length; i+=16)
|
||||
{
|
||||
CStdString strLine;
|
||||
strLine.Format("MEM_DUMP: %04x ", i);
|
||||
char *alpha = pData;
|
||||
for (int k=0; k < 4 && i + 4*k < length; k++)
|
||||
{
|
||||
for (int j=0; j < 4 && i + 4*k + j < length; j++)
|
||||
{
|
||||
CStdString strFormat;
|
||||
strFormat.Format(" %02x", *pData++);
|
||||
strLine += strFormat;
|
||||
}
|
||||
strLine += " ";
|
||||
}
|
||||
// pad with spaces
|
||||
while (strLine.size() < 13*4 + 16)
|
||||
strLine += " ";
|
||||
for (int j=0; j < 16 && i + j < length; j++)
|
||||
{
|
||||
if (*alpha > 31)
|
||||
strLine += *alpha;
|
||||
else
|
||||
strLine += '.';
|
||||
alpha++;
|
||||
}
|
||||
Log(LOGDEBUG, "%s", strLine.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void CLog::SetLogLevel(int level)
|
||||
{
|
||||
m_logLevel = level;
|
||||
CLog::Log(LOGNOTICE, "Log level changed to %d", m_logLevel);
|
||||
}
|
||||
|
||||
int CLog::GetLogLevel()
|
||||
{
|
||||
return m_logLevel;
|
||||
}
|
||||
|
||||
void CLog::OutputDebugString(const std::string& line)
|
||||
{
|
||||
#if defined(_DEBUG) || defined(PROFILE)
|
||||
::OutputDebugString(line.c_str());
|
||||
::OutputDebugString("\n");
|
||||
#endif
|
||||
}
|
||||
63
utils/log.h
Normal file
63
utils/log.h
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.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, 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 XBMC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
#define LOG_LEVEL_NONE -1 // nothing at all is logged
|
||||
#define LOG_LEVEL_NORMAL 0 // shows notice, error, severe and fatal
|
||||
#define LOG_LEVEL_DEBUG 1 // shows all
|
||||
#define LOG_LEVEL_DEBUG_FREEMEM 2 // shows all + shows freemem on screen
|
||||
#define LOG_LEVEL_DEBUG_SAMBA 3 // shows all + freemem on screen + samba debugging
|
||||
#define LOG_LEVEL_MAX LOG_LEVEL_DEBUG_SAMBA
|
||||
|
||||
// ones we use in the code
|
||||
#define LOGDEBUG 0
|
||||
#define LOGINFO 1
|
||||
#define LOGNOTICE 2
|
||||
#define LOGWARNING 3
|
||||
#define LOGERROR 4
|
||||
#define LOGSEVERE 5
|
||||
#define LOGFATAL 6
|
||||
#define LOGNONE 7
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define ATTRIB_LOG_FORMAT __attribute__((format(printf,2,3)))
|
||||
#else
|
||||
#define ATTRIB_LOG_FORMAT
|
||||
#endif
|
||||
|
||||
class CLog
|
||||
{
|
||||
public:
|
||||
CLog();
|
||||
virtual ~CLog(void);
|
||||
static void Close();
|
||||
static void Log(int loglevel, const char *format, ... ) ATTRIB_LOG_FORMAT;
|
||||
static void MemDump(char *pData, int length);
|
||||
static bool Init(const char* path);
|
||||
static void SetLogLevel(int level);
|
||||
static int GetLogLevel();
|
||||
private:
|
||||
static void OutputDebugString(const std::string& line);
|
||||
};
|
||||
Loading…
Reference in a new issue