Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

[rbp] added raspberrypi omxplayer

  • Loading branch information...
commit a91e8749e76f61e2c24ee87c16bae375674f8476 1 parent 18c401c
@huceke huceke authored
Showing with 12,219 additions and 3 deletions.
  1. +4 −0 Makefile.in
  2. +4 −0 Makefile.include.in
  3. +1 −1  tools/rbp/depends/xbmc/Makefile
  4. +4 −0 xbmc/Application.cpp
  5. +2 −0  xbmc/cores/dvdplayer/DVDMessageQueue.cpp
  6. +911 −0 xbmc/cores/omxplayer/BitstreamConverter.cpp
  7. +171 −0 xbmc/cores/omxplayer/BitstreamConverter.h
  8. +123 −0 xbmc/cores/omxplayer/DllOMX.h
  9. +20 −0 xbmc/cores/omxplayer/Makefile.in
  10. +1,478 −0 xbmc/cores/omxplayer/OMXAudio.cpp
  11. +155 −0 xbmc/cores/omxplayer/OMXAudio.h
  12. +119 −0 xbmc/cores/omxplayer/OMXAudioCodec.h
  13. +382 −0 xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp
  14. +77 −0 xbmc/cores/omxplayer/OMXAudioCodecOMX.h
  15. +1,114 −0 xbmc/cores/omxplayer/OMXImage.cpp
  16. +107 −0 xbmc/cores/omxplayer/OMXImage.h
  17. +3,816 −0 xbmc/cores/omxplayer/OMXPlayer.cpp
  18. +469 −0 xbmc/cores/omxplayer/OMXPlayer.h
  19. +847 −0 xbmc/cores/omxplayer/OMXPlayerAudio.cpp
  20. +130 −0 xbmc/cores/omxplayer/OMXPlayerAudio.h
  21. +816 −0 xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  22. +135 −0 xbmc/cores/omxplayer/OMXPlayerVideo.h
  23. +966 −0 xbmc/cores/omxplayer/OMXVideo.cpp
  24. +98 −0 xbmc/cores/omxplayer/OMXVideo.h
  25. +240 −0 xbmc/cores/omxplayer/OMXVideoCodec.h
  26. +6 −0 xbmc/cores/omxplayer/omxplayer_advancedsettings.xml
  27. +6 −0 xbmc/cores/playercorefactory/PlayerCoreConfig.h
  28. +7 −0 xbmc/cores/playercorefactory/PlayerCoreFactory.cpp
  29. +8 −2 xbmc/cores/playercorefactory/PlayerCoreFactory.h
  30. +3 −0  xbmc/video/windows/GUIWindowFullScreen.cpp
View
4 Makefile.in
@@ -143,6 +143,10 @@ ifeq (@USE_AMLPLAYER@,1)
DIRECTORY_ARCHIVES += xbmc/cores/amlplayer/amlplayer.a
endif
+ifeq (@USE_OMXPLAYER@,1)
+DIRECTORY_ARCHIVES += xbmc/cores/omxplayer/omxplayer.a
+endif
+
PAPCODECS_DIRS= \
lib/xbadpcm \
lib/nosefart \
View
4 Makefile.include.in
@@ -40,6 +40,10 @@ ifneq (@USE_EXTERNAL_FFMPEG@,1)
endif
INCLUDES+=-I@abs_top_srcdir@/xbmc/linux
INCLUDES+=-I@abs_top_srcdir@/xbmc/cores/dvdplayer
+ifeq (@USE_OMXPLAYER@,1)
+INCLUDES+=-I@abs_top_srcdir@/xbmc/cores/AudioEngine
+INCLUDES+=-I@abs_top_srcdir@/xbmc/cores/AudioEngine/Utils
+endif
DEFINES+= \
@ARCH_DEFINES@ \
-D_FILE_DEFINED \
View
2  tools/rbp/depends/xbmc/Makefile
@@ -12,7 +12,7 @@ CONFIGURE=./configure --prefix=$(PREFIX) --build=$(BUILD) --host=$(HOST) \
--disable-optical-drive --disable-dvdcss --disable-joystick --disable-debug \
--disable-crystalhd --disable-vtbdecoder --disable-vaapi --disable-vdpau \
--disable-pulse --disable-projectm --with-platform=raspberry-pi --disable-optimizations \
- --enable-rpi-cec-api
+ --enable-rpi-cec-api --enable-player=omxplayer
all: configure
View
4 xbmc/Application.cpp
@@ -5428,6 +5428,10 @@ void CApplication::SetHardwareVolume(float hardwareVolume)
value = 1.0f;
CAEFactory::SetVolume(value);
+
+ /* for platforms where we do not have AE */
+ if (m_pPlayer)
+ m_pPlayer->SetVolume(g_settings.m_fVolumeLevel);
}
int CApplication::GetVolume() const
View
2  xbmc/cores/dvdplayer/DVDMessageQueue.cpp
@@ -163,7 +163,9 @@ MsgQueueReturnCode CDVDMessageQueue::Get(CDVDMsg** pMsg, unsigned int iTimeoutIn
if(m_list.empty() && m_bEmptied == false && priority == 0 && m_owner != "teletext")
{
+#if !defined(TARGET_RASPBERRY_PI)
CLog::Log(LOGWARNING, "CDVDMessageQueue(%s)::Get - asked for new data packet, with nothing available", m_owner.c_str());
+#endif
m_bEmptied = true;
}
View
911 xbmc/cores/omxplayer/BitstreamConverter.cpp
@@ -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(AVIOContext *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->avio_wb32(pb, nal_end - nal_start);
+ m_dllAvFormat->avio_write(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)
+{
+ AVIOContext *pb;
+ int ret = m_dllAvFormat->avio_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->avio_close_dyn_buf(pb, buf);
+ return 0;
+}
+
+const int CBitstreamConverter::isom_write_avcc(AVIOContext *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->avio_w8(pb, 1); /* version */
+ m_dllAvFormat->avio_w8(pb, sps[1]); /* profile */
+ m_dllAvFormat->avio_w8(pb, sps[2]); /* profile compat */
+ m_dllAvFormat->avio_w8(pb, sps[3]); /* level */
+ m_dllAvFormat->avio_w8(pb, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */
+ m_dllAvFormat->avio_w8(pb, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */
+
+ m_dllAvFormat->avio_wb16(pb, sps_size);
+ m_dllAvFormat->avio_write(pb, sps, sps_size);
+ if (pps)
+ {
+ m_dllAvFormat->avio_w8(pb, 1); /* number of pps */
+ m_dllAvFormat->avio_wb16(pb, pps_size);
+ m_dllAvFormat->avio_write(pb, pps, pps_size);
+ }
+ m_dllAvUtil->av_free(start);
+ }
+ else
+ {
+ m_dllAvFormat->avio_write(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;
+
+ AVIOContext *pb;
+ if (m_dllAvFormat->avio_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->avio_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
+ AVIOContext *pb;
+
+ if(m_dllAvFormat->avio_open_dyn_buf(&pb) < 0)
+ {
+ return false;
+ }
+ m_convertSize = avc_parse_nal_units(pb, pData, iSize);
+ m_convertSize = m_dllAvFormat->avio_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
+ AVIOContext *pb;
+ if (m_dllAvFormat->avio_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->avio_wb16(pb, nal_size);
+ nal_start += 3;
+ m_dllAvFormat->avio_write(pb, nal_start, nal_size);
+ nal_start += nal_size;
+ }
+
+ m_convertSize = m_dllAvFormat->avio_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;
+
+ AVIOContext *pb;
+ if (m_dllAvFormat->avio_open_dyn_buf(&pb) < 0)
+ return false;
+
+ m_dllAvFormat->avio_w8(pb, 0);
+ m_dllAvFormat->avio_w8(pb, 0);
+ m_dllAvFormat->avio_w8(pb, !m_convert_vc1 ? 0 : 1);
+ m_dllAvFormat->avio_w8(pb, !m_convert_vc1 ? 0 : 0xd);
+ m_dllAvFormat->avio_write(pb, pData, iSize);
+ m_convertSize = m_dllAvFormat->avio_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;
+ }
+}
+
+
View
171 xbmc/cores/omxplayer/BitstreamConverter.h
@@ -0,0 +1,171 @@
+/*
+ * 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"
+
+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(AVIOContext *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(AVIOContext *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
View
123 xbmc/cores/omxplayer/DllOMX.h
@@ -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
View
20 xbmc/cores/omxplayer/Makefile.in
@@ -0,0 +1,20 @@
+CXXFLAGS += -D__STDC_FORMAT_MACROS
+
+SRCS= \
+ OMXPlayer.cpp \
+ OMXAudio.cpp \
+ OMXVideo.cpp \
+ OMXAudioCodecOMX.cpp \
+ OMXPlayerAudio.cpp \
+ OMXPlayerVideo.cpp \
+ OMXImage.cpp \
+ BitstreamConverter.cpp
+
+LIB= omxplayer.a
+
+@abs_top_srcdir@/system/advancedsettings.xml: $(LIB)
+ cp -f omxplayer_advancedsettings.xml $@
+
+include @abs_top_srcdir@/Makefile.include
+-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS)))
+
View
1,478 xbmc/cores/omxplayer/OMXAudio.cpp
@@ -0,0 +1,1478 @@
+/*
+* 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.
+*/
+
+#if (defined HAVE_CONFIG_H) && (!defined WIN32)
+ #include "config.h"
+#elif defined(_WIN32)
+#include "system.h"
+#endif
+
+#include "OMXAudio.h"
+#include "utils/log.h"
+
+#define CLASSNAME "COMXAudio"
+
+#include "linux/XMemUtils.h"
+
+#include "settings/AdvancedSettings.h"
+#include "settings/GUISettings.h"
+#include "settings/Settings.h"
+#include "guilib/LocalizeStrings.h"
+#include "cores/AudioEngine/Utils/AEConvert.h"
+
+#ifndef VOLUME_MINIMUM
+#define VOLUME_MINIMUM -6000 // -60dB
+#endif
+
+using namespace std;
+
+#define OMX_MAX_CHANNELS 9
+
+static enum AEChannel OMXChannelMap[OMX_MAX_CHANNELS] =
+{
+ AE_CH_FL , AE_CH_FR,
+ AE_CH_FC , AE_CH_LFE,
+ AE_CH_BL , AE_CH_BR,
+ AE_CH_SL , AE_CH_SR,
+ AE_CH_RAW
+};
+
+static enum OMX_AUDIO_CHANNELTYPE OMXChannels[OMX_MAX_CHANNELS] =
+{
+ OMX_AUDIO_ChannelLF, OMX_AUDIO_ChannelRF,
+ OMX_AUDIO_ChannelCF, OMX_AUDIO_ChannelLFE,
+ OMX_AUDIO_ChannelLR, OMX_AUDIO_ChannelRR,
+ OMX_AUDIO_ChannelLS, OMX_AUDIO_ChannelRS,
+ OMX_AUDIO_ChannelNone
+};
+
+static unsigned int WAVEChannels[OMX_MAX_CHANNELS] =
+{
+ SPEAKER_FRONT_LEFT, SPEAKER_FRONT_RIGHT,
+ SPEAKER_TOP_FRONT_CENTER, SPEAKER_LOW_FREQUENCY,
+ SPEAKER_BACK_LEFT, SPEAKER_BACK_RIGHT,
+ SPEAKER_SIDE_LEFT, SPEAKER_SIDE_RIGHT,
+ SPEAKER_SIDE_RIGHT
+};
+
+static const uint16_t AC3Bitrates[] = {32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 576, 640};
+static const uint16_t AC3FSCod [] = {48000, 44100, 32000, 0};
+
+static const uint16_t DTSFSCod [] = {0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0, 12000, 24000, 48000, 0, 0};
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+//***********************************************************************************************
+COMXAudio::COMXAudio() :
+ m_pCallback (NULL ),
+ m_Initialized (false ),
+ m_Pause (false ),
+ m_CanPause (false ),
+ m_CurrentVolume (0 ),
+ m_Passthrough (false ),
+ m_HWDecode (false ),
+ m_BytesPerSec (0 ),
+ m_BufferLen (0 ),
+ m_ChunkLen (0 ),
+ m_OutputChannels (0 ),
+ m_BitsPerSample (0 ),
+ m_omx_clock (NULL ),
+ m_av_clock (NULL ),
+ m_external_clock (false ),
+ m_first_frame (true ),
+ m_LostSync (true ),
+ m_SampleRate (0 ),
+ m_eEncoding (OMX_AUDIO_CodingPCM),
+ m_extradata (NULL ),
+ m_extrasize (0 ),
+ m_last_pts (DVD_NOPTS_VALUE)
+{
+ m_vizBufferSize = m_vizRemapBufferSize = 4096;
+ m_vizRemapBuffer = (uint8_t *)_aligned_malloc(m_vizRemapBufferSize,16);
+ m_vizBuffer = (uint8_t *)_aligned_malloc(m_vizBufferSize,16);
+}
+
+COMXAudio::~COMXAudio()
+{
+ if(m_Initialized)
+ Deinitialize();
+
+ _aligned_free(m_vizRemapBuffer);
+ _aligned_free(m_vizBuffer);
+}
+
+
+CAEChannelInfo COMXAudio::GetChannelLayout(AEAudioFormat format)
+{
+ unsigned int count = 0;
+
+ if(format.m_dataFormat == AE_FMT_AC3 ||
+ format.m_dataFormat == AE_FMT_DTS ||
+ format.m_dataFormat == AE_FMT_EAC3)
+ count = 2;
+ else if (format.m_dataFormat == AE_FMT_TRUEHD ||
+ format.m_dataFormat == AE_FMT_DTSHD)
+ count = 8;
+ else
+ {
+ for (unsigned int c = 0; c < 8; ++c)
+ {
+ for (unsigned int i = 0; i < format.m_channelLayout.Count(); ++i)
+ {
+ if (format.m_channelLayout[i] == OMXChannelMap[c])
+ {
+ count = c + 1;
+ break;
+ }
+ }
+ }
+ }
+
+ CAEChannelInfo info;
+ for (unsigned int i = 0; i < count; ++i)
+ info += OMXChannelMap[i];
+
+ return info;
+}
+
+bool COMXAudio::Initialize(AEAudioFormat format, std::string& device, OMXClock *clock, CDVDStreamInfo &hints, bool bUsePassthrough, bool bUseHWDecode)
+{
+ m_HWDecode = bUseHWDecode;
+ m_Passthrough = bUsePassthrough;
+
+ m_format = format;
+
+ if(hints.samplerate == 0)
+ return false;
+
+ /* passthrough overwrites hw decode */
+ if(m_Passthrough)
+ {
+ m_HWDecode = false;
+ }
+ else if(m_HWDecode)
+ {
+ /* check again if we are capable to hw decode the format */
+ m_HWDecode = CanHWDecode(hints.codec);
+ }
+ SetCodingType(format.m_dataFormat);
+
+ SetClock(clock);
+
+ if(hints.extrasize > 0 && hints.extradata != NULL)
+ {
+ m_extrasize = hints.extrasize;
+ m_extradata = (uint8_t *)malloc(m_extrasize);
+ memcpy(m_extradata, hints.extradata, hints.extrasize);
+ }
+
+ return Initialize(format, device);
+}
+
+bool COMXAudio::Initialize(AEAudioFormat format, std::string& device)
+{
+ if(m_Initialized)
+ Deinitialize();
+
+ m_format = format;
+
+ if(m_format.m_channelLayout.Count() == 0)
+ return false;
+
+ if(!m_dllAvUtil.Load())
+ return false;
+
+ if(m_av_clock == NULL)
+ {
+ /* no external clock set. generate one */
+ m_external_clock = false;
+
+ m_av_clock = new OMXClock();
+
+ if(!m_av_clock->OMXInitialize(false, true))
+ {
+ delete m_av_clock;
+ m_av_clock = NULL;
+ CLog::Log(LOGERROR, "COMXAudio::Initialize error creating av clock\n");
+ return false;
+ }
+ }
+
+ m_omx_clock = m_av_clock->GetOMXClock();
+
+ /*
+ m_Passthrough = false;
+
+ if(OMX_IS_RAW(m_format.m_dataFormat))
+ m_Passthrough =true;
+ */
+
+ m_drc = 0;
+
+ m_CurrentVolume = g_settings.m_fVolumeLevel;
+
+ memset(m_input_channels, 0x0, sizeof(m_input_channels));
+ memset(m_output_channels, 0x0, sizeof(m_output_channels));
+ memset(&m_wave_header, 0x0, sizeof(m_wave_header));
+
+ m_output_channels[0] = OMX_AUDIO_ChannelLF;
+ m_output_channels[1] = OMX_AUDIO_ChannelRF;
+ m_output_channels[2] = OMX_AUDIO_ChannelMax;
+
+ m_input_channels[0] = OMX_AUDIO_ChannelLF;
+ m_input_channels[1] = OMX_AUDIO_ChannelRF;
+ m_input_channels[2] = OMX_AUDIO_ChannelMax;
+
+ m_OutputChannels = 2;
+ m_wave_header.Format.nChannels = m_OutputChannels;
+ m_wave_header.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
+
+ if (!m_Passthrough)
+ {
+ /* setup output channel map */
+ /*
+ int ch = 0, map;
+ int chan = 0;
+ m_OutputChannels = 0;
+
+ for (unsigned int ch = 0; ch < m_format.m_channelLayout.Count(); ++ch)
+ {
+ for(map = 0; map < OMX_MAX_CHANNELS; ++map)
+ {
+ if (m_output_channels[ch] == OMXChannelMap[map])
+ {
+ printf("output %d\n", chan);
+ m_output_channels[chan] = OMXChannels[map];
+ chan++;
+ break;
+ }
+ }
+ }
+
+ m_OutputChannels = chan;
+ */
+
+ /* setup input channel map */
+ int map = 0;
+ int chan = 0;
+
+ for (unsigned int ch = 0; ch < m_format.m_channelLayout.Count(); ++ch)
+ {
+ for(map = 0; map < OMX_MAX_CHANNELS; ++map)
+ {
+ if (m_format.m_channelLayout[ch] == OMXChannelMap[map])
+ {
+ m_input_channels[chan] = OMXChannels[map];
+ m_wave_header.dwChannelMask |= WAVEChannels[map];
+ chan++;
+ break;
+ }
+ }
+ }
+
+ m_vizRemap.Initialize(m_format.m_channelLayout, CAEChannelInfo(AE_CH_LAYOUT_2_0), false, true);
+ }
+
+ OMX_INIT_STRUCTURE(m_pcm_output);
+ OMX_INIT_STRUCTURE(m_pcm_input);
+
+ memcpy(m_pcm_output.eChannelMapping, m_output_channels, sizeof(m_output_channels));
+ memcpy(m_pcm_input.eChannelMapping, m_input_channels, sizeof(m_input_channels));
+
+ // set the m_pcm_output parameters
+ m_pcm_output.eNumData = OMX_NumericalDataSigned;
+ m_pcm_output.eEndian = OMX_EndianLittle;
+ m_pcm_output.bInterleaved = OMX_TRUE;
+ m_pcm_output.nBitPerSample = CAEUtil::DataFormatToBits(m_format.m_dataFormat);
+ m_pcm_output.ePCMMode = OMX_AUDIO_PCMModeLinear;
+ m_pcm_output.nChannels = m_OutputChannels;
+ m_pcm_output.nSamplingRate = m_format.m_sampleRate;
+
+ m_SampleRate = m_format.m_sampleRate;
+ m_BitsPerSample = CAEUtil::DataFormatToBits(m_format.m_dataFormat);
+ m_BufferLen = m_BytesPerSec = m_format.m_sampleRate *
+ (CAEUtil::DataFormatToBits(m_format.m_dataFormat) >> 3) *
+ m_format.m_channelLayout.Count();
+ m_BufferLen *= AUDIO_BUFFER_SECONDS;
+ m_ChunkLen = 6144;
+
+ m_wave_header.Samples.wSamplesPerBlock = 0;
+ m_wave_header.Format.nChannels = m_format.m_channelLayout.Count();
+ m_wave_header.Format.nBlockAlign = m_format.m_channelLayout.Count() *
+ (CAEUtil::DataFormatToBits(m_format.m_dataFormat) >> 3);
+ m_wave_header.Format.wFormatTag = WAVE_FORMAT_PCM;
+ m_wave_header.Format.nSamplesPerSec = m_format.m_sampleRate;
+ m_wave_header.Format.nAvgBytesPerSec = m_BytesPerSec;
+ m_wave_header.Format.wBitsPerSample = CAEUtil::DataFormatToBits(m_format.m_dataFormat);
+ m_wave_header.Samples.wValidBitsPerSample = CAEUtil::DataFormatToBits(m_format.m_dataFormat);
+ m_wave_header.Format.cbSize = 0;
+ m_wave_header.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
+
+ m_pcm_input.eNumData = OMX_NumericalDataSigned;
+ m_pcm_input.eEndian = OMX_EndianLittle;
+ m_pcm_input.bInterleaved = OMX_TRUE;
+ m_pcm_input.nBitPerSample = CAEUtil::DataFormatToBits(m_format.m_dataFormat);
+ m_pcm_input.ePCMMode = OMX_AUDIO_PCMModeLinear;
+ m_pcm_input.nChannels = m_format.m_channelLayout.Count();
+ m_pcm_input.nSamplingRate = m_format.m_sampleRate;
+
+ OMX_ERRORTYPE omx_err = OMX_ErrorNone;
+ std::string componentName = "";
+
+ componentName = "OMX.broadcom.audio_render";
+ if(!m_omx_render.Initialize((const std::string)componentName, OMX_IndexParamAudioInit))
+ return false;
+
+ OMX_CONFIG_BRCMAUDIODESTINATIONTYPE audioDest;
+ OMX_INIT_STRUCTURE(audioDest);
+ strncpy((char *)audioDest.sName, device.c_str(), strlen(device.c_str()));
+
+ omx_err = m_omx_render.SetConfig(OMX_IndexConfigBrcmAudioDestination, &audioDest);
+ if (omx_err != OMX_ErrorNone)
+ return false;
+
+ OMX_CONFIG_BOOLEANTYPE configBool;
+ OMX_INIT_STRUCTURE(configBool);
+ configBool.bEnabled = OMX_FALSE;
+
+ omx_err = m_omx_render.SetConfig(OMX_IndexConfigBrcmClockReferenceSource, &configBool);
+ if (omx_err != OMX_ErrorNone)
+ return false;
+
+ componentName = "OMX.broadcom.audio_decode";
+ if(!m_omx_decoder.Initialize((const std::string)componentName, OMX_IndexParamAudioInit))
+ return false;
+
+ if(!m_Passthrough)
+ {
+ componentName = "OMX.broadcom.audio_mixer";
+ if(!m_omx_mixer.Initialize((const std::string)componentName, OMX_IndexParamAudioInit))
+ return false;
+ }
+
+ if(m_Passthrough)
+ {
+ OMX_CONFIG_BOOLEANTYPE boolType;
+ OMX_INIT_STRUCTURE(boolType);
+ boolType.bEnabled = OMX_TRUE;
+ omx_err = m_omx_decoder.SetParameter(OMX_IndexParamBrcmDecoderPassThrough, &boolType);
+ if(omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "COMXAudio::Initialize - Error OMX_IndexParamBrcmDecoderPassThrough 0x%08x", omx_err);
+ return false;
+ }
+ }
+
+ // set up the number/size of buffers
+ OMX_PARAM_PORTDEFINITIONTYPE port_param;
+ OMX_INIT_STRUCTURE(port_param);
+ port_param.nPortIndex = m_omx_decoder.GetInputPort();
+
+ omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &port_param);
+ if(omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "COMXAudio::Initialize error get OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err);
+ return false;
+ }
+
+ port_param.format.audio.eEncoding = m_eEncoding;
+
+ port_param.nBufferSize = m_ChunkLen;
+ port_param.nBufferCountActual = m_BufferLen / m_ChunkLen;
+
+ omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &port_param);
+ if(omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "COMXAudio::Initialize error set OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err);
+ return false;
+ }
+
+ if(m_HWDecode)
+ {
+ OMX_AUDIO_PARAM_PORTFORMATTYPE formatType;
+ OMX_INIT_STRUCTURE(formatType);
+ formatType.nPortIndex = m_omx_decoder.GetInputPort();
+
+ formatType.eEncoding = m_eEncoding;
+
+ omx_err = m_omx_decoder.SetParameter(OMX_IndexParamAudioPortFormat, &formatType);
+ if(omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "COMXAudio::Initialize error OMX_IndexParamAudioPortFormat omx_err(0x%08x)\n", omx_err);
+ return false;
+ }
+ }
+
+ m_omx_tunnel_clock.Initialize(m_omx_clock, m_omx_clock->GetInputPort(), &m_omx_render, m_omx_render.GetInputPort()+1);
+
+ omx_err = m_omx_tunnel_clock.Establish(false);
+ if(omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "COMXAudio::Initialize m_omx_tunnel_clock.Establish\n");
+ return false;
+ }
+
+ if(!m_external_clock)
+ {
+ omx_err = m_omx_clock->SetStateForComponent(OMX_StateExecuting);
+ if (omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "COMXAudio::Initialize m_omx_clock.SetStateForComponent\n");
+ return false;
+ }
+ }
+
+ omx_err = m_omx_decoder.AllocInputBuffers();
+ if(omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "COMXAudio::Initialize - Error alloc buffers 0x%08x", omx_err);
+ return false;
+ }
+
+ if(!m_Passthrough)
+ {
+ m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_mixer, m_omx_mixer.GetInputPort());
+ omx_err = m_omx_tunnel_decoder.Establish(false);
+ if(omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "COMXAudio::Initialize - Error m_omx_tunnel_decoder.Establish 0x%08x", omx_err);
+ return false;
+ }
+
+ omx_err = m_omx_decoder.SetStateForComponent(OMX_StateExecuting);
+ if(omx_err != OMX_ErrorNone) {
+ CLog::Log(LOGERROR, "COMXAudio::Initialize - Error setting OMX_StateExecuting 0x%08x", omx_err);
+ return false;
+ }
+
+ m_omx_tunnel_mixer.Initialize(&m_omx_mixer, m_omx_mixer.GetOutputPort(), &m_omx_render, m_omx_render.GetInputPort());
+ omx_err = m_omx_tunnel_mixer.Establish(false);
+ if(omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "COMXAudio::Initialize - Error m_omx_tunnel_decoder.Establish 0x%08x", omx_err);
+ return false;
+ }
+
+ omx_err = m_omx_mixer.SetStateForComponent(OMX_StateExecuting);
+ if(omx_err != OMX_ErrorNone) {
+ CLog::Log(LOGERROR, "COMXAudio::Initialize - Error setting OMX_StateExecuting 0x%08x", omx_err);
+ return false;
+ }
+ }
+ else
+ {
+ m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_render, m_omx_render.GetInputPort());
+ omx_err = m_omx_tunnel_decoder.Establish(false);
+ if(omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "COMXAudio::Initialize - Error m_omx_tunnel_decoder.Establish 0x%08x", omx_err);
+ return false;
+ }
+
+ omx_err = m_omx_decoder.SetStateForComponent(OMX_StateExecuting);
+ if(omx_err != OMX_ErrorNone) {
+ CLog::Log(LOGERROR, "COMXAudio::Initialize - Error setting OMX_StateExecuting 0x%08x", omx_err);
+ return false;
+ }
+ }
+
+ omx_err = m_omx_render.SetStateForComponent(OMX_StateExecuting);
+ if(omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "COMXAudio::Initialize - Error setting OMX_StateExecuting 0x%08x", omx_err);
+ return false;
+ }
+
+ if(m_eEncoding == OMX_AUDIO_CodingPCM)
+ {
+ OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer();
+ if(omx_buffer == NULL)
+ {
+ CLog::Log(LOGERROR, "COMXAudio::Initialize - buffer error 0x%08x", omx_err);
+ return false;
+ }
+
+ omx_buffer->nOffset = 0;
+ omx_buffer->nFilledLen = sizeof(m_wave_header);
+ if(omx_buffer->nFilledLen > omx_buffer->nAllocLen)
+ {
+ CLog::Log(LOGERROR, "COMXAudio::Initialize - omx_buffer->nFilledLen > omx_buffer->nAllocLen");
+ return false;
+ }
+ memset((unsigned char *)omx_buffer->pBuffer, 0x0, omx_buffer->nAllocLen);
+ memcpy((unsigned char *)omx_buffer->pBuffer, &m_wave_header, omx_buffer->nFilledLen);
+ omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME;
+
+ omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
+ if (omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err);
+ return false;
+ }
+ }
+ else if(m_HWDecode)
+ {
+ // send decoder config
+ if(m_extrasize > 0 && m_extradata != NULL)
+ {
+ OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer();
+
+ if(omx_buffer == NULL)
+ {
+ CLog::Log(LOGERROR, "%s::%s - buffer error 0x%08x", CLASSNAME, __func__, omx_err);
+ return false;
+ }
+
+ omx_buffer->nOffset = 0;
+ omx_buffer->nFilledLen = m_extrasize;
+ if(omx_buffer->nFilledLen > omx_buffer->nAllocLen)
+ {
+ CLog::Log(LOGERROR, "%s::%s - omx_buffer->nFilledLen > omx_buffer->nAllocLen", CLASSNAME, __func__);
+ return false;
+ }
+
+ memset((unsigned char *)omx_buffer->pBuffer, 0x0, omx_buffer->nAllocLen);
+ memcpy((unsigned char *)omx_buffer->pBuffer, m_extradata, omx_buffer->nFilledLen);
+ omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME;
+
+ omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
+ if (omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err);
+ return false;
+ }
+ }
+ }
+
+ m_Initialized = true;
+ m_first_frame = true;
+ m_last_pts = DVD_NOPTS_VALUE;
+
+ SetCurrentVolume(m_CurrentVolume);
+
+ CLog::Log(LOGDEBUG, "COMXAudio::Initialize Ouput bps %d samplerate %d channels %d buffer size %d bytes per second %d",
+ (int)m_pcm_output.nBitPerSample, (int)m_pcm_output.nSamplingRate, (int)m_pcm_output.nChannels, m_BufferLen, m_BytesPerSec);
+ CLog::Log(LOGDEBUG, "COMXAudio::Initialize Input bps %d samplerate %d channels %d buffer size %d bytes per second %d",
+ (int)m_pcm_input.nBitPerSample, (int)m_pcm_input.nSamplingRate, (int)m_pcm_input.nChannels, m_BufferLen, m_BytesPerSec);
+ CLog::Log(LOGDEBUG, "COMXAudio::Initialize device %s passthrough %d hwdecode %d external clock %d",
+ device.c_str(), m_Passthrough, m_HWDecode, m_external_clock);
+
+ m_av_clock->OMXStateExecute(false);
+
+ return true;
+}
+
+//***********************************************************************************************
+bool COMXAudio::Deinitialize()
+{
+ if(!m_Initialized)
+ return true;
+
+ /*
+ if(m_av_clock && !m_external_clock)
+ m_av_clock->OMXStop();
+ */
+
+ if(m_av_clock && !m_external_clock)
+ {
+ m_av_clock->Lock();
+ m_av_clock->OMXStop(false);
+ }
+
+ m_omx_tunnel_decoder.Flush();
+ if(!m_Passthrough)
+ m_omx_tunnel_mixer.Flush();
+ m_omx_tunnel_clock.Flush();
+
+ m_omx_tunnel_clock.Deestablish();
+ if(!m_Passthrough)
+ m_omx_tunnel_mixer.Deestablish();
+ m_omx_tunnel_decoder.Deestablish();
+
+ m_omx_decoder.FlushInput();
+
+ m_omx_render.Deinitialize();
+ if(!m_Passthrough)
+ m_omx_mixer.Deinitialize();
+ m_omx_decoder.Deinitialize();
+
+ m_Initialized = false;
+ m_BytesPerSec = 0;
+ m_BufferLen = 0;
+
+ if(m_av_clock && !m_external_clock)
+ {
+ m_av_clock->OMXReset(false);
+ m_av_clock->UnLock();
+ }
+
+ if(!m_external_clock && m_av_clock != NULL)
+ {
+ delete m_av_clock;
+ m_av_clock = NULL;
+ m_external_clock = false;
+ }
+
+ m_omx_clock = NULL;
+ m_av_clock = NULL;
+
+ m_Initialized = false;
+ m_LostSync = true;
+ m_HWDecode = false;
+
+ if(m_extradata)
+ free(m_extradata);
+ m_extradata = NULL;
+ m_extrasize = 0;
+
+ m_dllAvUtil.Unload();
+
+ m_first_frame = true;
+ m_last_pts = DVD_NOPTS_VALUE;
+
+ return true;
+}
+
+void COMXAudio::Flush()
+{
+ if(!m_Initialized)
+ return;
+
+ m_omx_decoder.FlushInput();
+ m_omx_tunnel_decoder.Flush();
+ if(!m_Passthrough)
+ m_omx_tunnel_mixer.Flush();
+
+ m_last_pts = DVD_NOPTS_VALUE;
+ m_LostSync = true;
+ //m_first_frame = true;
+}
+
+//***********************************************************************************************
+bool COMXAudio::Pause()
+{
+ if (!m_Initialized)
+ return -1;
+
+ if(m_Pause) return true;
+ m_Pause = true;
+
+ m_omx_decoder.SetStateForComponent(OMX_StatePause);
+
+ return true;
+}
+
+//***********************************************************************************************
+bool COMXAudio::Resume()
+{
+ if (!m_Initialized)
+ return -1;
+
+ if(!m_Pause) return true;
+ m_Pause = false;
+
+ m_omx_decoder.SetStateForComponent(OMX_StateExecuting);
+
+ return true;
+}
+
+//***********************************************************************************************
+bool COMXAudio::Stop()
+{
+ if (!m_Initialized)
+ return -1;
+
+ Flush();
+
+ m_Pause = false;
+
+ return true;
+}
+
+//***********************************************************************************************
+long COMXAudio::GetCurrentVolume() const
+{
+ return m_CurrentVolume;
+}
+
+//***********************************************************************************************
+void COMXAudio::Mute(bool bMute)
+{
+ if(!m_Initialized)
+ return;
+
+ if (bMute)
+ SetCurrentVolume(VOLUME_MINIMUM);
+ else
+ SetCurrentVolume(m_CurrentVolume);
+}
+
+//***********************************************************************************************
+bool COMXAudio::SetCurrentVolume(float fVolume)
+{
+ if(!m_Initialized || m_Passthrough)
+ return -1;
+
+ m_CurrentVolume = fVolume;
+
+ OMX_AUDIO_CONFIG_VOLUMETYPE volume;
+ OMX_INIT_STRUCTURE(volume);
+ volume.nPortIndex = m_omx_render.GetInputPort();
+
+ volume.bLinear = OMX_TRUE;
+ float hardwareVolume = std::max(VOLUME_MINIMUM, std::min(VOLUME_MAXIMUM, fVolume)) * 100.0f;
+ volume.sVolume.nValue = (int)hardwareVolume;
+
+ m_omx_render.SetConfig(OMX_IndexConfigAudioVolume, &volume);
+
+ return true;
+}
+
+
+//***********************************************************************************************
+unsigned int COMXAudio::AddPackets(const void* data, unsigned int len)
+{
+ return AddPackets(data, len, 0, 0);
+}
+
+//***********************************************************************************************
+unsigned int COMXAudio::AddPackets(const void* data, unsigned int len, double dts, double pts)
+{
+ if(!m_Initialized)
+ {
+ CLog::Log(LOGERROR,"COMXAudio::AddPackets - sanity failed. no valid play handle!");
+ return len;
+ }
+
+ m_vizBufferSamples = 0;
+
+ if (!m_Passthrough && m_pCallback && len)
+ {
+ /* unput samples */
+ m_vizBufferSamples = len / (CAEUtil::DataFormatToBits(AE_FMT_S16LE) >> 3);
+ CAEConvert::AEConvertToFn m_convertFn = CAEConvert::ToFloat(AE_FMT_S16LE);
+ /* input frames */
+ unsigned int frames = m_vizBufferSamples / m_format.m_channelLayout.Count();
+
+ /* check convert buffer */
+ CheckOutputBufferSize((void **)&m_vizBuffer, &m_vizBufferSize, m_vizBufferSamples * (CAEUtil::DataFormatToBits(AE_FMT_FLOAT) >> 3));
+
+ /* convert to float */
+ m_convertFn((uint8_t *)data, m_vizBufferSamples, (float *)m_vizBuffer);
+
+ /* check remap buffer */
+ CheckOutputBufferSize((void **)&m_vizRemapBuffer, &m_vizRemapBufferSize, frames * 2 * (CAEUtil::DataFormatToBits(AE_FMT_FLOAT) >> 3));
+
+ /* remap */
+ m_vizRemap.Remap((float *)m_vizBuffer, (float*)m_vizRemapBuffer, frames);
+
+ /* output samples */
+ m_vizBufferSamples = m_vizBufferSamples / m_format.m_channelLayout.Count() * 2;
+
+ /* viz size is limited */
+ if(m_vizBufferSamples > VIS_PACKET_SIZE)
+ m_vizBufferSamples = VIS_PACKET_SIZE;
+
+ if(m_pCallback)
+ m_pCallback->OnAudioData((float *)m_vizRemapBuffer, m_vizBufferSamples);
+ }
+
+ if(m_eEncoding == OMX_AUDIO_CodingDTS && m_LostSync && (m_Passthrough || m_HWDecode))
+ {
+ int skip = SyncDTS((uint8_t *)data, len);
+ if(skip > 0)
+ return len;
+ }
+
+ if(m_eEncoding == OMX_AUDIO_CodingDDP && m_LostSync && (m_Passthrough || m_HWDecode))
+ {
+ int skip = SyncAC3((uint8_t *)data, len);
+ if(skip > 0)
+ return len;
+ }
+
+ unsigned int demuxer_bytes = (unsigned int)len;
+ uint8_t *demuxer_content = (uint8_t *)data;
+
+ OMX_ERRORTYPE omx_err;
+
+ OMX_BUFFERHEADERTYPE *omx_buffer = NULL;
+
+ while(demuxer_bytes)
+ {
+ // 200ms timeout
+ omx_buffer = m_omx_decoder.GetInputBuffer(200);
+
+ if(omx_buffer == NULL)
+ {
+ CLog::Log(LOGERROR, "COMXAudio::Decode timeout\n");
+ return len;
+ }
+
+ omx_buffer->nOffset = 0;
+ omx_buffer->nFlags = 0;
+
+ omx_buffer->nFilledLen = (demuxer_bytes > omx_buffer->nAllocLen) ? omx_buffer->nAllocLen : demuxer_bytes;
+ memcpy(omx_buffer->pBuffer, demuxer_content, omx_buffer->nFilledLen);
+
+ uint64_t val = (uint64_t)(pts == DVD_NOPTS_VALUE) ? 0 : pts;
+
+ if(m_av_clock->AudioStart())
+ {
+ omx_buffer->nFlags = OMX_BUFFERFLAG_STARTTIME;
+
+ m_last_pts = pts;
+
+ CLog::Log(LOGDEBUG, "ADec : setStartTime %f\n", (float)val / DVD_TIME_BASE);
+ m_av_clock->AudioStart(false);
+ }
+ else
+ {
+ if(pts == DVD_NOPTS_VALUE)
+ {
+ omx_buffer->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN;
+ m_last_pts = pts;
+ }
+ else if (m_last_pts != pts)
+ {
+ if(pts > m_last_pts)
+ m_last_pts = pts;
+ else
+ omx_buffer->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN;;
+ }
+ else if (m_last_pts == pts)
+ {
+ omx_buffer->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN;
+ }
+ }
+
+ omx_buffer->nTimeStamp = ToOMXTime(val);
+
+ demuxer_bytes -= omx_buffer->nFilledLen;
+ demuxer_content += omx_buffer->nFilledLen;
+
+ if(demuxer_bytes == 0)
+ omx_buffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
+
+ int nRetry = 0;
+ while(true)
+ {
+ omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
+ if (omx_err == OMX_ErrorNone)
+ {
+ break;
+ }
+ else
+ {
+ CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err);
+ nRetry++;
+ }
+ if(nRetry == 5)
+ {
+ CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() finaly failed\n", CLASSNAME, __func__);
+ return 0;
+ }
+ }
+
+ if(m_first_frame)
+ {
+ m_first_frame = false;
+ //m_omx_render.WaitForEvent(OMX_EventPortSettingsChanged);
+
+ m_omx_render.DisablePort(m_omx_render.GetInputPort(), false);
+ if(!m_Passthrough)
+ {
+ m_omx_mixer.DisablePort(m_omx_mixer.GetOutputPort(), false);
+ m_omx_mixer.DisablePort(m_omx_mixer.GetInputPort(), false);
+ }
+ m_omx_decoder.DisablePort(m_omx_decoder.GetOutputPort(), false);
+
+ if(!m_Passthrough)
+ {
+ OMX_INIT_STRUCTURE(m_pcm_input);
+ m_pcm_input.nPortIndex = m_omx_decoder.GetOutputPort();
+ omx_err = m_omx_decoder.GetParameter(OMX_IndexParamAudioPcm, &m_pcm_input);
+ if(omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "COMXAudio::AddPackets error GetParameter 1 omx_err(0x%08x)\n", omx_err);
+ }
+
+ if (g_guiSettings.GetBool("audiooutput.normalizelevels"))
+ {
+ OMX_AUDIO_CONFIG_VOLUMETYPE volume;
+ OMX_INIT_STRUCTURE(volume);
+ volume.nPortIndex = m_omx_mixer.GetInputPort();
+ volume.bLinear = OMX_FALSE;
+ volume.sVolume.nValue = (int)(g_advancedSettings.m_ac3Gain*100.0f+0.5f);
+ m_omx_mixer.SetConfig(OMX_IndexConfigAudioVolume, &volume);
+ }
+
+ memcpy(m_pcm_input.eChannelMapping, m_input_channels, sizeof(m_input_channels));
+ m_pcm_input.nSamplingRate = m_format.m_sampleRate;
+
+ /* setup mixer input */
+ m_pcm_input.nPortIndex = m_omx_mixer.GetInputPort();
+ omx_err = m_omx_mixer.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_input);
+ if(omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "COMXAudio::AddPackets error SetParameter 1 input omx_err(0x%08x)\n", omx_err);
+ }
+ omx_err = m_omx_mixer.GetParameter(OMX_IndexParamAudioPcm, &m_pcm_input);
+ if(omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "COMXAudio::AddPackets error GetParameter 2 input omx_err(0x%08x)\n", omx_err);
+ }
+
+ m_pcm_output.nSamplingRate = m_format.m_sampleRate;
+
+ /* setup mixer output */
+ m_pcm_output.nPortIndex = m_omx_mixer.GetOutputPort();
+ omx_err = m_omx_mixer.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
+ if(omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "COMXAudio::AddPackets error SetParameter 1 output omx_err(0x%08x)\n", omx_err);
+ }
+ omx_err = m_omx_mixer.GetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
+ if(omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "COMXAudio::AddPackets error GetParameter 2 output omx_err(0x%08x)\n", omx_err);
+ }
+
+ m_pcm_output.nSamplingRate = m_format.m_sampleRate;
+
+ m_pcm_output.nPortIndex = m_omx_render.GetInputPort();
+ omx_err = m_omx_render.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
+ if(omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "COMXAudio::AddPackets error SetParameter 1 render omx_err(0x%08x)\n", omx_err);
+ }
+ omx_err = m_omx_render.GetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
+ if(omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "COMXAudio::AddPackets error GetParameter 2 render omx_err(0x%08x)\n", omx_err);
+ }
+
+ PrintPCM(&m_pcm_input, std::string("input"));
+ PrintPCM(&m_pcm_output, std::string("output"));
+ }
+ else
+ {
+ m_pcm_output.nPortIndex = m_omx_decoder.GetOutputPort();
+ m_omx_decoder.GetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
+ PrintPCM(&m_pcm_output, std::string("output"));
+
+ OMX_AUDIO_PARAM_PORTFORMATTYPE formatType;
+ OMX_INIT_STRUCTURE(formatType);
+ formatType.nPortIndex = m_omx_render.GetInputPort();
+
+ omx_err = m_omx_render.GetParameter(OMX_IndexParamAudioPortFormat, &formatType);
+ if(omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "COMXAudio::AddPackets error OMX_IndexParamAudioPortFormat omx_err(0x%08x)\n", omx_err);
+ assert(0);
+ }
+
+ formatType.eEncoding = m_eEncoding;
+
+ omx_err = m_omx_render.SetParameter(OMX_IndexParamAudioPortFormat, &formatType);
+ if(omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "COMXAudio::AddPackets error OMX_IndexParamAudioPortFormat omx_err(0x%08x)\n", omx_err);
+ assert(0);
+ }
+
+ if(m_eEncoding == OMX_AUDIO_CodingDDP)
+ {
+ OMX_AUDIO_PARAM_DDPTYPE m_ddParam;
+ OMX_INIT_STRUCTURE(m_ddParam);
+
+ m_ddParam.nPortIndex = m_omx_render.GetInputPort();
+
+ m_ddParam.nChannels = m_format.m_channelLayout.Count(); //(m_InputChannels == 6) ? 8 : m_InputChannels;
+ m_ddParam.nSampleRate = m_SampleRate;
+ m_ddParam.eBitStreamId = OMX_AUDIO_DDPBitStreamIdAC3;
+ m_ddParam.nBitRate = 0;
+
+ for(unsigned int i = 0; i < OMX_MAX_CHANNELS; i++)
+ {
+ if(i >= m_ddParam.nChannels)
+ break;
+
+ m_ddParam.eChannelMapping[i] = OMXChannels[i];
+ }
+
+ m_omx_render.SetParameter(OMX_IndexParamAudioDdp, &m_ddParam);
+ m_omx_render.GetParameter(OMX_IndexParamAudioDdp, &m_ddParam);
+ PrintDDP(&m_ddParam);
+ }
+ else if(m_eEncoding == OMX_AUDIO_CodingDTS)
+ {
+ m_dtsParam.nPortIndex = m_omx_render.GetInputPort();
+
+ m_dtsParam.nChannels = m_format.m_channelLayout.Count(); //(m_InputChannels == 6) ? 8 : m_InputChannels;
+ m_dtsParam.nBitRate = 0;
+
+ for(unsigned int i = 0; i < OMX_MAX_CHANNELS; i++)
+ {
+ if(i >= m_dtsParam.nChannels)
+ break;
+
+ m_dtsParam.eChannelMapping[i] = OMXChannels[i];
+ }
+
+ m_omx_render.SetParameter(OMX_IndexParamAudioDts, &m_dtsParam);
+ m_omx_render.GetParameter(OMX_IndexParamAudioDts, &m_dtsParam);
+ PrintDTS(&m_dtsParam);
+ }
+ }
+
+ m_omx_render.EnablePort(m_omx_render.GetInputPort(), false);
+ if(!m_Passthrough)
+ {
+ m_omx_mixer.EnablePort(m_omx_mixer.GetOutputPort(), false);
+ m_omx_mixer.EnablePort(m_omx_mixer.GetInputPort(), false);
+ }
+ m_omx_decoder.EnablePort(m_omx_decoder.GetOutputPort(), false);
+ }
+
+ }
+
+ return len;
+}
+
+//***********************************************************************************************
+unsigned int COMXAudio::GetSpace()
+{
+ int free = m_omx_decoder.GetInputBufferSpace();
+ return free;
+}
+
+float COMXAudio::GetDelay()
+{
+ unsigned int free = m_omx_decoder.GetInputBufferSize() - m_omx_decoder.GetInputBufferSpace();
+ return (float)free / (float)m_BytesPerSec;
+}
+
+float COMXAudio::GetCacheTime()
+{
+ float fBufferLenFull = (float)m_BufferLen - (float)GetSpace();
+ if(fBufferLenFull < 0)
+ fBufferLenFull = 0;
+ float ret = fBufferLenFull / (float)m_BytesPerSec;
+ return ret;
+}
+
+float COMXAudio::GetCacheTotal()
+{
+ return (float)m_BufferLen / (float)m_BytesPerSec;
+}
+
+//***********************************************************************************************
+unsigned int COMXAudio::GetChunkLen()
+{
+ return m_ChunkLen;
+}
+//***********************************************************************************************
+int COMXAudio::SetPlaySpeed(int iSpeed)
+{
+ return 0;
+}
+
+void COMXAudio::RegisterAudioCallback(IAudioCallback *pCallback)
+{
+ m_pCallback = pCallback;
+ if (m_pCallback && !m_Passthrough && !m_HWDecode)
+ m_pCallback->OnInitialize(m_OutputChannels, m_SampleRate, m_BitsPerSample);
+}
+
+void COMXAudio::UnRegisterAudioCallback()
+{
+ m_pCallback = NULL;
+}
+
+void COMXAudio::DoAudioWork()
+{
+ if (m_pCallback && m_vizBufferSamples)
+ {
+ m_pCallback->OnAudioData((float*)m_vizBuffer, m_vizBufferSamples);
+ m_vizBufferSamples = 0;
+ }
+}
+
+void COMXAudio::WaitCompletion()
+{
+ if(!m_Initialized || m_Pause)
+ return;
+
+ OMX_ERRORTYPE omx_err = OMX_ErrorNone;
+ OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer();
+ struct timespec starttime, endtime;
+
+ if(omx_buffer == NULL)
+ {
+ CLog::Log(LOGERROR, "%s::%s - buffer error 0x%08x", CLASSNAME, __func__, omx_err);
+ return;
+ }
+
+ omx_buffer->nOffset = 0;
+ omx_buffer->nFilledLen = 0;
+ omx_buffer->nTimeStamp = ToOMXTime(0LL);
+
+ omx_buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS | OMX_BUFFERFLAG_TIME_UNKNOWN;
+
+ omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
+ if (omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err);
+ return;
+ }
+
+ clock_gettime(CLOCK_REALTIME, &starttime);
+
+ while(true)
+ {
+ if(m_omx_render.IsEOS())
+ break;
+ clock_gettime(CLOCK_REALTIME, &endtime);
+ if((endtime.tv_sec - starttime.tv_sec) > 2)
+ {
+ CLog::Log(LOGERROR, "%s::%s - wait for eos timed out\n", CLASSNAME, __func__);
+ break;
+ }
+ Sleep(50);
+ }
+
+ return;
+}
+
+void COMXAudio::SwitchChannels(int iAudioStream, bool bAudioOnAllSpeakers)
+{
+ return ;
+}
+
+bool COMXAudio::SetClock(OMXClock *clock)
+{
+ if(m_av_clock != NULL)
+ return false;
+
+ m_av_clock = clock;
+ m_external_clock = true;
+ return true;
+}
+
+void COMXAudio::SetCodingType(AEDataFormat dataFormat)
+{
+ switch(dataFormat)
+ {
+ case AE_FMT_DTS:
+ CLog::Log(LOGDEBUG, "COMXAudio::SetCodingType OMX_AUDIO_CodingDTS\n");
+ m_eEncoding = OMX_AUDIO_CodingDTS;
+ break;
+ case AE_FMT_AC3:
+ case AE_FMT_EAC3:
+ CLog::Log(LOGDEBUG, "COMXAudio::SetCodingType OMX_AUDIO_CodingDDP\n");
+ m_eEncoding = OMX_AUDIO_CodingDDP;
+ break;
+ default:
+ CLog::Log(LOGDEBUG, "COMXAudio::SetCodingType OMX_AUDIO_CodingPCM\n");
+ m_eEncoding = OMX_AUDIO_CodingPCM;
+ break;
+ }
+}
+
+bool COMXAudio::CanHWDecode(CodecID codec)
+{
+ bool ret = false;
+ switch(codec)
+ {
+ case CODEC_ID_DTS:
+ CLog::Log(LOGDEBUG, "COMXAudio::CanHWDecode OMX_AUDIO_CodingDTS\n");
+ ret = true;
+ break;
+ case CODEC_ID_AC3:
+ case CODEC_ID_EAC3:
+ CLog::Log(LOGDEBUG, "COMXAudio::CanHWDecode OMX_AUDIO_CodingDDP\n");
+ ret = true;
+ break;
+ default:
+ CLog::Log(LOGDEBUG, "COMXAudio::CanHWDecode OMX_AUDIO_CodingPCM\n");
+ ret = false;
+ break;
+ }
+
+ return ret;
+}
+
+void COMXAudio::PrintChannels(OMX_AUDIO_CHANNELTYPE eChannelMapping[])
+{
+ for(int i = 0; i < OMX_AUDIO_MAXCHANNELS; i++)
+ {
+ switch(eChannelMapping[i])
+ {
+ case OMX_AUDIO_ChannelLF:
+ CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelLF\n");