aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Op den Kamp <lars@opdenkamp.eu>2011-01-23 03:26:52 +0100
committerLars Op den Kamp <lars@opdenkamp.eu>2011-01-23 03:26:52 +0100
commit4e98a514c6a2975ec234fe19fe058e7e74bcfb7d (patch)
tree678a498293daf821732088ef837c6525363cdc2d
parentb7ed68894bbdb0c92d9547a54644dc252ac70dd5 (diff)
parent8d73cbde1dcd240d80bee9301d0321703a15c995 (diff)
Merge remote branch 'upstream/master'
-rw-r--r--addons/skin.confluence/media/flagging/audio/dtshd_hra.pngbin0 -> 10467 bytes
-rw-r--r--addons/skin.confluence/media/flagging/audio/dtshd_ma.pngbin0 -> 10321 bytes
-rw-r--r--system/players/dvdplayer/avcodec-52.dllbin4585616 -> 4590327 bytes
-rw-r--r--system/players/dvdplayer/avformat-52.dllbin710734 -> 710734 bytes
-rw-r--r--system/players/dvdplayer/avutil-50.dllbin145620 -> 145620 bytes
-rw-r--r--system/players/dvdplayer/postproc-51.dllbin182916 -> 182916 bytes
-rw-r--r--system/players/dvdplayer/swscale-0.6.1.dllbin364482 -> 364482 bytes
-rw-r--r--xbmc/cdrip/CDDARipper.cpp5
-rw-r--r--xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/aacenc.c6
-rw-r--r--xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/avcodec.h24
-rw-r--r--xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/dca.c361
-rw-r--r--xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/h264.c13
-rw-r--r--xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/libfaac.c9
-rw-r--r--xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/options.c5
-rw-r--r--xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/utils.c21
-rw-r--r--xbmc/cores/dvdplayer/Codecs/ffmpeg/libavutil/common.h17
-rw-r--r--xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0039-Add-av_popcount-to-libavutil-common.h-and-bump-minor.patch47
-rw-r--r--xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0040-added-export-DTS-profile-information-in-ffmpeg.patch498
-rw-r--r--xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0041-Add-av_get_profile_name-to-get-profile-names.patch84
-rw-r--r--xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0042-Show-profile-in-avcodec_string.patch55
-rw-r--r--xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0043-h264-add-profile-names-for-the-existing-defines.patch51
-rw-r--r--xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0044-aacenc-add-recognized-profiles-array.patch36
-rw-r--r--xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0045-libfaac-add-recognized-profiles-array.patch39
-rw-r--r--xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0046-dca-add-profile-names.patch40
-rw-r--r--xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0047-dca-consider-a-stream-with-XXCh-X96-in-ExSS-as-DTS-H.patch37
-rw-r--r--xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.cpp12
-rw-r--r--xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h3
-rw-r--r--xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp15
-rw-r--r--xbmc/lib/libjsonrpc/TCPServer.cpp1
-rw-r--r--xbmc/utils/Builtins.cpp19
-rw-r--r--xbmc/utils/StreamDetails.cpp9
31 files changed, 1397 insertions, 10 deletions
diff --git a/addons/skin.confluence/media/flagging/audio/dtshd_hra.png b/addons/skin.confluence/media/flagging/audio/dtshd_hra.png
new file mode 100644
index 0000000000..7a60c9fea6
--- /dev/null
+++ b/addons/skin.confluence/media/flagging/audio/dtshd_hra.png
Binary files differ
diff --git a/addons/skin.confluence/media/flagging/audio/dtshd_ma.png b/addons/skin.confluence/media/flagging/audio/dtshd_ma.png
new file mode 100644
index 0000000000..71e743ec38
--- /dev/null
+++ b/addons/skin.confluence/media/flagging/audio/dtshd_ma.png
Binary files differ
diff --git a/system/players/dvdplayer/avcodec-52.dll b/system/players/dvdplayer/avcodec-52.dll
index ae847eeb0a..5b5d531298 100644
--- a/system/players/dvdplayer/avcodec-52.dll
+++ b/system/players/dvdplayer/avcodec-52.dll
Binary files differ
diff --git a/system/players/dvdplayer/avformat-52.dll b/system/players/dvdplayer/avformat-52.dll
index 83247ac686..f0b2e7a878 100644
--- a/system/players/dvdplayer/avformat-52.dll
+++ b/system/players/dvdplayer/avformat-52.dll
Binary files differ
diff --git a/system/players/dvdplayer/avutil-50.dll b/system/players/dvdplayer/avutil-50.dll
index 45c439a001..d098b67dab 100644
--- a/system/players/dvdplayer/avutil-50.dll
+++ b/system/players/dvdplayer/avutil-50.dll
Binary files differ
diff --git a/system/players/dvdplayer/postproc-51.dll b/system/players/dvdplayer/postproc-51.dll
index 03c227532e..a9713d17e7 100644
--- a/system/players/dvdplayer/postproc-51.dll
+++ b/system/players/dvdplayer/postproc-51.dll
Binary files differ
diff --git a/system/players/dvdplayer/swscale-0.6.1.dll b/system/players/dvdplayer/swscale-0.6.1.dll
index 5efdb3e5b3..f6cdd001b2 100644
--- a/system/players/dvdplayer/swscale-0.6.1.dll
+++ b/system/players/dvdplayer/swscale-0.6.1.dll
Binary files differ
diff --git a/xbmc/cdrip/CDDARipper.cpp b/xbmc/cdrip/CDDARipper.cpp
index e6b6d2cd0a..557f271288 100644
--- a/xbmc/cdrip/CDDARipper.cpp
+++ b/xbmc/cdrip/CDDARipper.cpp
@@ -266,7 +266,7 @@ bool CCDDARipper::RipTrack(CFileItem* pItem)
if (!CreateAlbumDir(*pItem->GetMusicInfoTag(), strDirectory, legalType))
return false;
- CStdString strFile = CUtil::MakeLegalPath(CUtil::AddFileToFolder(strDirectory, GetTrackName(pItem)), legalType);
+ CStdString strFile = CUtil::AddFileToFolder(strDirectory, CUtil::MakeLegalFileName(GetTrackName(pItem), legalType));
return Rip(pItem->m_strPath, strFile.c_str(), *pItem->GetMusicInfoTag());
}
@@ -310,10 +310,9 @@ bool CCDDARipper::RipCD()
for (int i = 0; i < vecItems.Size(); i++)
{
CFileItemPtr item = vecItems[i];
- CStdString track(GetTrackName(item.get()));
// construct filename
- CStdString strFile = CUtil::MakeLegalPath(CUtil::AddFileToFolder(strDirectory, track), legalType);
+ CStdString strFile = CUtil::AddFileToFolder(strDirectory, CUtil::MakeLegalFileName(GetTrackName(item.get()), legalType));
unsigned int tick = CTimeUtils::GetTimeMS();
diff --git a/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/aacenc.c b/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/aacenc.c
index f122fe11ac..94fb13fd85 100644
--- a/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/aacenc.c
+++ b/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/aacenc.c
@@ -636,6 +636,11 @@ static av_cold int aac_encode_end(AVCodecContext *avctx)
return 0;
}
+static const AVProfile profiles[] = {
+ { FF_PROFILE_AAC_LOW, "Low" },
+ { FF_PROFILE_UNKNOWN },
+};
+
AVCodec aac_encoder = {
"aac",
AVMEDIA_TYPE_AUDIO,
@@ -647,4 +652,5 @@ AVCodec aac_encoder = {
.capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
.sample_fmts = (const enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_NONE},
.long_name = NULL_IF_CONFIG_SMALL("Advanced Audio Coding"),
+ .profiles = profiles,
};
diff --git a/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/avcodec.h b/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/avcodec.h
index 705a747ff8..59ac3ba601 100644
--- a/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/avcodec.h
+++ b/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/avcodec.h
@@ -2179,6 +2179,12 @@ typedef struct AVCodecContext {
#define FF_PROFILE_AAC_SSR 2
#define FF_PROFILE_AAC_LTP 3
+#define FF_PROFILE_DTS 20
+#define FF_PROFILE_DTS_ES 30
+#define FF_PROFILE_DTS_96_24 40
+#define FF_PROFILE_DTS_HD_HRA 50
+#define FF_PROFILE_DTS_HD_MA 60
+
#define FF_PROFILE_H264_BASELINE 66
#define FF_PROFILE_H264_MAIN 77
#define FF_PROFILE_H264_EXTENDED 88
@@ -2709,6 +2715,14 @@ typedef struct AVCodecContext {
} AVCodecContext;
/**
+ * AVProfile.
+ */
+typedef struct AVProfile {
+ int profile;
+ const char *name; ///< short name for the profile
+} AVProfile;
+
+/**
* AVCodec.
*/
typedef struct AVCodec {
@@ -2748,6 +2762,7 @@ typedef struct AVCodec {
const enum SampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1
const int64_t *channel_layouts; ///< array of support channel layouts, or NULL if unknown. array is terminated by 0
uint8_t max_lowres; ///< maximum value for lowres supported by the decoder
+ const AVProfile *profiles; ///< array of recognized profiles, or NULL if unknown, array is terminated by {FF_PROFILE_UNKNOWN}
} AVCodec;
/**
@@ -3305,6 +3320,15 @@ AVCodec *avcodec_find_decoder_by_name(const char *name);
void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode);
/**
+ * Return a name for the specified profile, if available.
+ *
+ * @param codec the codec that is searched for the given profile
+ * @param profile the profile value for which a name is requested
+ * @return A name for the profile if found, NULL otherwise.
+ */
+const char *av_get_profile_name(const AVCodec *codec, int profile);
+
+/**
* Set the fields of the given AVCodecContext to default values.
*
* @param s The AVCodecContext of which the fields should be set to default values.
diff --git a/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/dca.c b/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/dca.c
index 7168f41b60..9817790e5f 100644
--- a/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/dca.c
+++ b/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/dca.c
@@ -26,6 +26,7 @@
#include <stddef.h>
#include <stdio.h>
+#include "libavutil/common.h"
#include "libavutil/intmath.h"
#include "libavutil/intreadwrite.h"
#include "avcodec.h"
@@ -63,6 +64,39 @@ enum DCAMode {
DCA_4F2R
};
+/* these are unconfirmed but should be mostly correct */
+enum DCAExSSSpeakerMask {
+ DCA_EXSS_FRONT_CENTER = 0x0001,
+ DCA_EXSS_FRONT_LEFT_RIGHT = 0x0002,
+ DCA_EXSS_SIDE_REAR_LEFT_RIGHT = 0x0004,
+ DCA_EXSS_LFE = 0x0008,
+ DCA_EXSS_REAR_CENTER = 0x0010,
+ DCA_EXSS_FRONT_HIGH_LEFT_RIGHT = 0x0020,
+ DCA_EXSS_REAR_LEFT_RIGHT = 0x0040,
+ DCA_EXSS_FRONT_HIGH_CENTER = 0x0080,
+ DCA_EXSS_OVERHEAD = 0x0100,
+ DCA_EXSS_CENTER_LEFT_RIGHT = 0x0200,
+ DCA_EXSS_WIDE_LEFT_RIGHT = 0x0400,
+ DCA_EXSS_SIDE_LEFT_RIGHT = 0x0800,
+ DCA_EXSS_LFE2 = 0x1000,
+ DCA_EXSS_SIDE_HIGH_LEFT_RIGHT = 0x2000,
+ DCA_EXSS_REAR_HIGH_CENTER = 0x4000,
+ DCA_EXSS_REAR_HIGH_LEFT_RIGHT = 0x8000,
+};
+
+enum DCAExtensionMask {
+ DCA_EXT_CORE = 0x001, ///< core in core substream
+ DCA_EXT_XXCH = 0x002, ///< XXCh channels extension in core substream
+ DCA_EXT_X96 = 0x004, ///< 96/24 extension in core substream
+ DCA_EXT_XCH = 0x008, ///< XCh channel extension in core substream
+ DCA_EXT_EXSS_CORE = 0x010, ///< core in ExSS (extension substream)
+ DCA_EXT_EXSS_XBR = 0x020, ///< extended bitrate extension in ExSS
+ DCA_EXT_EXSS_XXCH = 0x040, ///< XXCh channels extension in ExSS
+ DCA_EXT_EXSS_X96 = 0x080, ///< 96/24 extension in ExSS
+ DCA_EXT_EXSS_LBR = 0x100, ///< low bitrate component in ExSS
+ DCA_EXT_EXSS_XLL = 0x200, ///< lossless extension in ExSS
+};
+
/* Tables for mapping dts channel configurations to libavcodec multichannel api.
* Some compromises have been made for special configurations. Most configurations
* are never used so complete accuracy is not needed.
@@ -182,6 +216,7 @@ static const int8_t dca_channel_reorder_nolfe_xch[][9] = {
#define HEADER_SIZE 14
#define DCA_MAX_FRAME_SIZE 16384
+#define DCA_MAX_EXSS_HEADER_SIZE 4096
/** Bit allocation */
typedef struct {
@@ -279,7 +314,7 @@ typedef struct {
DECLARE_ALIGNED(16, float, samples)[(DCA_PRIM_CHANNELS_MAX+1)*256];
const float *samples_chanptr[DCA_PRIM_CHANNELS_MAX+1];
- uint8_t dca_buffer[DCA_MAX_FRAME_SIZE];
+ uint8_t dca_buffer[DCA_MAX_FRAME_SIZE + DCA_MAX_EXSS_HEADER_SIZE];
int dca_buffer_size; ///< how much data is in the dca_buffer
const int8_t* channel_order_tab; ///< channel reordering table, lfe and non lfe
@@ -292,6 +327,18 @@ typedef struct {
int xch_present;
int xch_base_channel; ///< index of first (only) channel containing XCH data
+ /* Other detected extensions in the core substream */
+ int xxch_present;
+ int x96_present;
+
+ /* ExSS header parser */
+ int static_fields; ///< static fields present
+ int mix_metadata; ///< mixing metadata present
+ int num_mix_configs; ///< number of mix out configurations
+ int mix_config_num_ch[4]; ///< number of channels in each mix out configuration
+
+ int profile;
+
int debug_flag; ///< used for suppressing repeated error messages output
DSPContext dsp;
FFTContext imdct;
@@ -1251,6 +1298,275 @@ static int dca_convert_bitstream(const uint8_t * src, int src_size, uint8_t * ds
}
/**
+ * Return the number of channels in an ExSS speaker mask (HD)
+ */
+static int dca_exss_mask2count(int mask)
+{
+ /* count bits that mean speaker pairs twice */
+ return av_popcount(mask)
+ + av_popcount(mask & (
+ DCA_EXSS_CENTER_LEFT_RIGHT
+ | DCA_EXSS_FRONT_LEFT_RIGHT
+ | DCA_EXSS_FRONT_HIGH_LEFT_RIGHT
+ | DCA_EXSS_WIDE_LEFT_RIGHT
+ | DCA_EXSS_SIDE_LEFT_RIGHT
+ | DCA_EXSS_SIDE_HIGH_LEFT_RIGHT
+ | DCA_EXSS_SIDE_REAR_LEFT_RIGHT
+ | DCA_EXSS_REAR_LEFT_RIGHT
+ | DCA_EXSS_REAR_HIGH_LEFT_RIGHT
+ ));
+}
+
+/**
+ * Skip mixing coefficients of a single mix out configuration (HD)
+ */
+static void dca_exss_skip_mix_coeffs(GetBitContext *gb, int channels, int out_ch)
+{
+ for (int i = 0; i < channels; i++) {
+ int mix_map_mask = get_bits(gb, out_ch);
+ int num_coeffs = av_popcount(mix_map_mask);
+ skip_bits_long(gb, num_coeffs * 6);
+ }
+}
+
+/**
+ * Parse extension substream asset header (HD)
+ */
+static int dca_exss_parse_asset_header(DCAContext *s)
+{
+ int header_pos = get_bits_count(&s->gb);
+ int header_size;
+ int channels;
+ int embedded_stereo = 0;
+ int embedded_6ch = 0;
+ int drc_code_present;
+ int extensions_mask;
+ int i, j;
+
+ if (get_bits_left(&s->gb) < 16)
+ return -1;
+
+ /* We will parse just enough to get to the extensions bitmask with which
+ * we can set the profile value. */
+
+ header_size = get_bits(&s->gb, 9) + 1;
+ skip_bits(&s->gb, 3); // asset index
+
+ if (s->static_fields) {
+ if (get_bits1(&s->gb))
+ skip_bits(&s->gb, 4); // asset type descriptor
+ if (get_bits1(&s->gb))
+ skip_bits_long(&s->gb, 24); // language descriptor
+
+ if (get_bits1(&s->gb)) {
+ /* How can one fit 1024 bytes of text here if the maximum value
+ * for the asset header size field above was 512 bytes? */
+ int text_length = get_bits(&s->gb, 10) + 1;
+ if (get_bits_left(&s->gb) < text_length * 8)
+ return -1;
+ skip_bits_long(&s->gb, text_length * 8); // info text
+ }
+
+ skip_bits(&s->gb, 5); // bit resolution - 1
+ skip_bits(&s->gb, 4); // max sample rate code
+ channels = get_bits(&s->gb, 8) + 1;
+
+ if (get_bits1(&s->gb)) { // 1-to-1 channels to speakers
+ int spkr_remap_sets;
+ int spkr_mask_size = 16;
+ int num_spkrs[7];
+
+ if (channels > 2)
+ embedded_stereo = get_bits1(&s->gb);
+ if (channels > 6)
+ embedded_6ch = get_bits1(&s->gb);
+
+ if (get_bits1(&s->gb)) {
+ spkr_mask_size = (get_bits(&s->gb, 2) + 1) << 2;
+ skip_bits(&s->gb, spkr_mask_size); // spkr activity mask
+ }
+
+ spkr_remap_sets = get_bits(&s->gb, 3);
+
+ for (i = 0; i < spkr_remap_sets; i++) {
+ /* std layout mask for each remap set */
+ num_spkrs[i] = dca_exss_mask2count(get_bits(&s->gb, spkr_mask_size));
+ }
+
+ for (i = 0; i < spkr_remap_sets; i++) {
+ int num_dec_ch_remaps = get_bits(&s->gb, 5) + 1;
+ if (get_bits_left(&s->gb) < 0)
+ return -1;
+
+ for (j = 0; j < num_spkrs[i]; j++) {
+ int remap_dec_ch_mask = get_bits_long(&s->gb, num_dec_ch_remaps);
+ int num_dec_ch = av_popcount(remap_dec_ch_mask);
+ skip_bits_long(&s->gb, num_dec_ch * 5); // remap codes
+ }
+ }
+
+ } else {
+ skip_bits(&s->gb, 3); // representation type
+ }
+ }
+
+ drc_code_present = get_bits1(&s->gb);
+ if (drc_code_present)
+ get_bits(&s->gb, 8); // drc code
+
+ if (get_bits1(&s->gb))
+ skip_bits(&s->gb, 5); // dialog normalization code
+
+ if (drc_code_present && embedded_stereo)
+ get_bits(&s->gb, 8); // drc stereo code
+
+ if (s->mix_metadata && get_bits1(&s->gb)) {
+ skip_bits(&s->gb, 1); // external mix
+ skip_bits(&s->gb, 6); // post mix gain code
+
+ if (get_bits(&s->gb, 2) != 3) // mixer drc code
+ skip_bits(&s->gb, 3); // drc limit
+ else
+ skip_bits(&s->gb, 8); // custom drc code
+
+ if (get_bits1(&s->gb)) // channel specific scaling
+ for (i = 0; i < s->num_mix_configs; i++)
+ skip_bits_long(&s->gb, s->mix_config_num_ch[i] * 6); // scale codes
+ else
+ skip_bits_long(&s->gb, s->num_mix_configs * 6); // scale codes
+
+ for (i = 0; i < s->num_mix_configs; i++) {
+ if (get_bits_left(&s->gb) < 0)
+ return -1;
+ dca_exss_skip_mix_coeffs(&s->gb, channels, s->mix_config_num_ch[i]);
+ if (embedded_6ch)
+ dca_exss_skip_mix_coeffs(&s->gb, 6, s->mix_config_num_ch[i]);
+ if (embedded_stereo)
+ dca_exss_skip_mix_coeffs(&s->gb, 2, s->mix_config_num_ch[i]);
+ }
+ }
+
+ switch (get_bits(&s->gb, 2)) {
+ case 0: extensions_mask = get_bits(&s->gb, 12); break;
+ case 1: extensions_mask = DCA_EXT_EXSS_XLL; break;
+ case 2: extensions_mask = DCA_EXT_EXSS_LBR; break;
+ case 3: extensions_mask = 0; /* aux coding */ break;
+ }
+
+ /* not parsed further, we were only interested in the extensions mask */
+
+ if (get_bits_left(&s->gb) < 0)
+ return -1;
+
+ if (get_bits_count(&s->gb) - header_pos > header_size * 8) {
+ av_log(s->avctx, AV_LOG_WARNING, "Asset header size mismatch.\n");
+ return -1;
+ }
+ skip_bits_long(&s->gb, header_pos + header_size * 8 - get_bits_count(&s->gb));
+
+ if (extensions_mask & DCA_EXT_EXSS_XLL)
+ s->profile = FF_PROFILE_DTS_HD_MA;
+ else if (extensions_mask & (DCA_EXT_EXSS_XBR | DCA_EXT_EXSS_X96 |
+ DCA_EXT_EXSS_XXCH))
+ s->profile = FF_PROFILE_DTS_HD_HRA;
+
+ if (!(extensions_mask & DCA_EXT_CORE))
+ av_log(s->avctx, AV_LOG_WARNING, "DTS core detection mismatch.\n");
+ if (!!(extensions_mask & DCA_EXT_XCH) != s->xch_present)
+ av_log(s->avctx, AV_LOG_WARNING, "DTS XCh detection mismatch.\n");
+ if (!!(extensions_mask & DCA_EXT_XXCH) != s->xxch_present)
+ av_log(s->avctx, AV_LOG_WARNING, "DTS XXCh detection mismatch.\n");
+ if (!!(extensions_mask & DCA_EXT_X96) != s->x96_present)
+ av_log(s->avctx, AV_LOG_WARNING, "DTS X96 detection mismatch.\n");
+
+ return 0;
+}
+
+/**
+ * Parse extension substream header (HD)
+ */
+static void dca_exss_parse_header(DCAContext *s)
+{
+ int ss_index;
+ int blownup;
+ int header_size;
+ int hd_size;
+ int num_audiop = 1;
+ int num_assets = 1;
+ int active_ss_mask[8];
+ int i, j;
+
+ if (get_bits_left(&s->gb) < 52)
+ return;
+
+ skip_bits(&s->gb, 8); // user data
+ ss_index = get_bits(&s->gb, 2);
+
+ blownup = get_bits1(&s->gb);
+ header_size = get_bits(&s->gb, 8 + 4 * blownup) + 1;
+ hd_size = get_bits_long(&s->gb, 16 + 4 * blownup) + 1;
+
+ s->static_fields = get_bits1(&s->gb);
+ if (s->static_fields) {
+ skip_bits(&s->gb, 2); // reference clock code
+ skip_bits(&s->gb, 3); // frame duration code
+
+ if (get_bits1(&s->gb))
+ skip_bits_long(&s->gb, 36); // timestamp
+
+ /* a single stream can contain multiple audio assets that can be
+ * combined to form multiple audio presentations */
+
+ num_audiop = get_bits(&s->gb, 3) + 1;
+ if (num_audiop > 1) {
+ av_log_ask_for_sample(s->avctx, "Multiple DTS-HD audio presentations.");
+ /* ignore such streams for now */
+ return;
+ }
+
+ num_assets = get_bits(&s->gb, 3) + 1;
+ if (num_assets > 1) {
+ av_log_ask_for_sample(s->avctx, "Multiple DTS-HD audio assets.");
+ /* ignore such streams for now */
+ return;
+ }
+
+ for (i = 0; i < num_audiop; i++)
+ active_ss_mask[i] = get_bits(&s->gb, ss_index + 1);
+
+ for (i = 0; i < num_audiop; i++)
+ for (j = 0; j <= ss_index; j++)
+ if (active_ss_mask[i] & (1 << j))
+ skip_bits(&s->gb, 8); // active asset mask
+
+ s->mix_metadata = get_bits1(&s->gb);
+ if (s->mix_metadata) {
+ int mix_out_mask_size;
+
+ skip_bits(&s->gb, 2); // adjustment level
+ mix_out_mask_size = (get_bits(&s->gb, 2) + 1) << 2;
+ s->num_mix_configs = get_bits(&s->gb, 2) + 1;
+
+ for (i = 0; i < s->num_mix_configs; i++) {
+ int mix_out_mask = get_bits(&s->gb, mix_out_mask_size);
+ s->mix_config_num_ch[i] = dca_exss_mask2count(mix_out_mask);
+ }
+ }
+ }
+
+ for (i = 0; i < num_assets; i++)
+ skip_bits_long(&s->gb, 16 + 4 * blownup); // asset size
+
+ for (i = 0; i < num_assets; i++) {
+ if (dca_exss_parse_asset_header(s))
+ return;
+ }
+
+ /* not parsed further, we were only interested in the extensions mask
+ * from the asset header */
+}
+
+/**
* Main frame decoding function
* FIXME add arguments
*/
@@ -1267,10 +1583,15 @@ static int dca_decode_frame(AVCodecContext * avctx,
int16_t *samples = data;
DCAContext *s = avctx->priv_data;
int channels;
+ int core_ss_end;
s->xch_present = 0;
- s->dca_buffer_size = dca_convert_bitstream(buf, buf_size, s->dca_buffer, DCA_MAX_FRAME_SIZE);
+ s->x96_present = 0;
+ s->xxch_present = 0;
+
+ s->dca_buffer_size = dca_convert_bitstream(buf, buf_size, s->dca_buffer,
+ DCA_MAX_FRAME_SIZE + DCA_MAX_EXSS_HEADER_SIZE);
if (s->dca_buffer_size == -1) {
av_log(avctx, AV_LOG_ERROR, "Not a valid DCA frame\n");
return -1;
@@ -1287,6 +1608,8 @@ static int dca_decode_frame(AVCodecContext * avctx,
avctx->bit_rate = s->bit_rate;
avctx->frame_size = s->sample_blocks * 32;
+ s->profile = FF_PROFILE_DTS;
+
for (i = 0; i < (s->sample_blocks / 8); i++) {
dca_decode_block(s, 0, i);
}
@@ -1297,7 +1620,9 @@ static int dca_decode_frame(AVCodecContext * avctx,
/* extensions start at 32-bit boundaries into bitstream */
skip_bits_long(&s->gb, (-get_bits_count(&s->gb)) & 31);
- while(get_bits_left(&s->gb) >= 32) {
+ core_ss_end = FFMIN(s->frame_size, s->dca_buffer_size) * 8;
+
+ while(core_ss_end - get_bits_count(&s->gb) >= 32) {
uint32_t bits = get_bits_long(&s->gb, 32);
switch(bits) {
@@ -1315,6 +1640,8 @@ static int dca_decode_frame(AVCodecContext * avctx,
/* skip length-to-end-of-frame field for the moment */
skip_bits(&s->gb, 10);
+ s->profile = FFMAX(s->profile, FF_PROFILE_DTS_ES);
+
/* extension amode should == 1, number of channels in extension */
/* AFAIK XCh is not used for more channels */
if ((ext_amode = get_bits(&s->gb, 4)) != 1) {
@@ -1333,16 +1660,34 @@ static int dca_decode_frame(AVCodecContext * avctx,
s->xch_present = 1;
break;
}
+ case 0x47004a03:
+ /* XXCh: extended channels */
+ /* usually found either in core or HD part in DTS-HD HRA streams,
+ * but not in DTS-ES which contains XCh extensions instead */
+ s->xxch_present = 1;
+ s->profile = FFMAX(s->profile, FF_PROFILE_DTS_ES);
+ break;
+
case 0x1d95f262:
av_log(avctx, AV_LOG_DEBUG, "Possible X96 extension found at %d bits\n", get_bits_count(&s->gb));
av_log(avctx, AV_LOG_DEBUG, "FSIZE96 = %d bytes\n", get_bits(&s->gb, 12)+1);
av_log(avctx, AV_LOG_DEBUG, "REVNO = %d\n", get_bits(&s->gb, 4));
+
+ s->x96_present = 1;
+ s->profile = FFMAX(s->profile, FF_PROFILE_DTS_96_24);
break;
}
skip_bits_long(&s->gb, (-get_bits_count(&s->gb)) & 31);
}
+ /* check for ExSS (HD part) */
+ if (s->dca_buffer_size - s->frame_size > 32
+ && get_bits_long(&s->gb, 32) == DCA_HD_MARKER)
+ dca_exss_parse_header(s);
+
+ avctx->profile = s->profile;
+
channels = s->prim_channels + !!s->lfe;
if (s->amode<16) {
@@ -1472,6 +1817,15 @@ static av_cold int dca_decode_end(AVCodecContext * avctx)
return 0;
}
+static const AVProfile profiles[] = {
+ { FF_PROFILE_DTS, "DTS" },
+ { FF_PROFILE_DTS_ES, "DTS-ES" },
+ { FF_PROFILE_DTS_96_24, "DTS 96/24" },
+ { FF_PROFILE_DTS_HD_HRA, "DTS-HD HRA" },
+ { FF_PROFILE_DTS_HD_MA, "DTS-HD MA" },
+ { FF_PROFILE_UNKNOWN },
+};
+
AVCodec dca_decoder = {
.name = "dca",
.type = AVMEDIA_TYPE_AUDIO,
@@ -1481,4 +1835,5 @@ AVCodec dca_decoder = {
.decode = dca_decode_frame,
.close = dca_decode_end,
.long_name = NULL_IF_CONFIG_SMALL("DCA (DTS Coherent Acoustics)"),
+ .profiles = profiles,
};
diff --git a/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/h264.c b/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/h264.c
index d1662fcb6b..fb3fc1efb6 100644
--- a/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/h264.c
+++ b/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/h264.c
@@ -3382,6 +3382,17 @@ av_cold int ff_h264_decode_end(AVCodecContext *avctx)
return 0;
}
+static const AVProfile profiles[] = {
+ { FF_PROFILE_H264_BASELINE, "Baseline" },
+ { FF_PROFILE_H264_MAIN, "Main" },
+ { FF_PROFILE_H264_EXTENDED, "Extended" },
+ { FF_PROFILE_H264_HIGH, "High" },
+ { FF_PROFILE_H264_HIGH_10, "High 10" },
+ { FF_PROFILE_H264_HIGH_422, "High 4:2:2" },
+ { FF_PROFILE_H264_HIGH_444, "High 4:4:4" },
+ { FF_PROFILE_H264_CAVLC_444, "CAVLC 4:4:4" },
+ { FF_PROFILE_UNKNOWN },
+};
AVCodec h264_decoder = {
"h264",
@@ -3395,6 +3406,7 @@ AVCodec h264_decoder = {
/*CODEC_CAP_DRAW_HORIZ_BAND |*/ CODEC_CAP_DR1 | CODEC_CAP_DELAY,
.flush= flush_dpb,
.long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"),
+ .profiles = profiles,
};
#if CONFIG_H264_VDPAU_DECODER
@@ -3411,5 +3423,6 @@ AVCodec h264_vdpau_decoder = {
.flush= flush_dpb,
.long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (VDPAU acceleration)"),
.pix_fmts = (const enum PixelFormat[]){PIX_FMT_VDPAU_H264, PIX_FMT_NONE},
+ .profiles = profiles,
};
#endif
diff --git a/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/libfaac.c b/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/libfaac.c
index 82fd05bafd..bf403567c5 100644
--- a/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/libfaac.c
+++ b/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/libfaac.c
@@ -145,6 +145,14 @@ static av_cold int Faac_encode_close(AVCodecContext *avctx)
return 0;
}
+static const AVProfile profiles[] = {
+ { FF_PROFILE_AAC_MAIN, "Main" },
+ { FF_PROFILE_AAC_LOW, "Low" },
+ { FF_PROFILE_AAC_SSR, "SSR" },
+ { FF_PROFILE_AAC_LTP, "LTP" },
+ { FF_PROFILE_UNKNOWN },
+};
+
AVCodec libfaac_encoder = {
"libfaac",
AVMEDIA_TYPE_AUDIO,
@@ -155,4 +163,5 @@ AVCodec libfaac_encoder = {
Faac_encode_close,
.sample_fmts = (const enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_NONE},
.long_name = NULL_IF_CONFIG_SMALL("libfaac AAC (Advanced Audio Codec)"),
+ .profiles = profiles,
};
diff --git a/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/options.c b/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/options.c
index 744957dc5f..c59e92bffa 100644
--- a/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/options.c
+++ b/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/options.c
@@ -331,6 +331,11 @@ static const AVOption options[]={
{"aac_low", NULL, 0, FF_OPT_TYPE_CONST, FF_PROFILE_AAC_LOW, INT_MIN, INT_MAX, A|E, "profile"},
{"aac_ssr", NULL, 0, FF_OPT_TYPE_CONST, FF_PROFILE_AAC_SSR, INT_MIN, INT_MAX, A|E, "profile"},
{"aac_ltp", NULL, 0, FF_OPT_TYPE_CONST, FF_PROFILE_AAC_LTP, INT_MIN, INT_MAX, A|E, "profile"},
+{"dts", NULL, 0, FF_OPT_TYPE_CONST, FF_PROFILE_DTS, INT_MIN, INT_MAX, A|E, "profile"},
+{"dts_es", NULL, 0, FF_OPT_TYPE_CONST, FF_PROFILE_DTS_ES, INT_MIN, INT_MAX, A|E, "profile"},
+{"dts_96_24", NULL, 0, FF_OPT_TYPE_CONST, FF_PROFILE_DTS_96_24, INT_MIN, INT_MAX, A|E, "profile"},
+{"dts_hd_hra", NULL, 0, FF_OPT_TYPE_CONST, FF_PROFILE_DTS_HD_HRA, INT_MIN, INT_MAX, A|E, "profile"},
+{"dts_hd_ma", NULL, 0, FF_OPT_TYPE_CONST, FF_PROFILE_DTS_HD_MA, INT_MIN, INT_MAX, A|E, "profile"},
{"level", NULL, OFFSET(level), FF_OPT_TYPE_INT, FF_LEVEL_UNKNOWN, INT_MIN, INT_MAX, V|A|E, "level"},
{"unknown", NULL, 0, FF_OPT_TYPE_CONST, FF_LEVEL_UNKNOWN, INT_MIN, INT_MAX, V|A|E, "level"},
{"lowres", "decode at 1= 1/2, 2=1/4, 3=1/8 resolutions", OFFSET(lowres), FF_OPT_TYPE_INT, 0, 0, INT_MAX, V|D},
diff --git a/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/utils.c b/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/utils.c
index f21e9eda7b..cfcd7082bb 100644
--- a/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/utils.c
+++ b/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavcodec/utils.c
@@ -840,6 +840,7 @@ size_t av_get_codec_tag_string(char *buf, size_t buf_size, unsigned int codec_ta
void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
{
const char *codec_name;
+ const char *profile = NULL;
AVCodec *p;
char buf1[32];
int bitrate;
@@ -852,6 +853,7 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
if (p) {
codec_name = p->name;
+ profile = av_get_profile_name(p, enc->profile);
} else if (enc->codec_id == CODEC_ID_MPEG2TS) {
/* fake mpeg2 transport stream codec (currently not
registered) */
@@ -871,6 +873,9 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
snprintf(buf, buf_size,
"Video: %s%s",
codec_name, enc->mb_decision ? " (hq)" : "");
+ if (profile)
+ snprintf(buf + strlen(buf), buf_size - strlen(buf),
+ " (%s)", profile);
if (enc->pix_fmt != PIX_FMT_NONE) {
snprintf(buf + strlen(buf), buf_size - strlen(buf),
", %s",
@@ -906,6 +911,9 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
snprintf(buf, buf_size,
"Audio: %s",
codec_name);
+ if (profile)
+ snprintf(buf + strlen(buf), buf_size - strlen(buf),
+ " (%s)", profile);
if (enc->sample_rate) {
snprintf(buf + strlen(buf), buf_size - strlen(buf),
", %d Hz", enc->sample_rate);
@@ -945,6 +953,19 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
}
}
+const char *av_get_profile_name(const AVCodec *codec, int profile)
+{
+ const AVProfile *p;
+ if (profile == FF_PROFILE_UNKNOWN || !codec->profiles)
+ return NULL;
+
+ for (p = codec->profiles; p->profile != FF_PROFILE_UNKNOWN; p++)
+ if (p->profile == profile)
+ return p->name;
+
+ return NULL;
+}
+
unsigned avcodec_version( void )
{
return LIBAVCODEC_VERSION_INT;
diff --git a/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavutil/common.h b/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavutil/common.h
index 76cf5520b4..5577a55bba 100644
--- a/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavutil/common.h
+++ b/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavutil/common.h
@@ -186,6 +186,20 @@ static inline av_const int av_ceil_log2_c(int x)
return av_log2((x - 1) << 1);
}
+/**
+ * Count number of bits set to one in x
+ * @param x value to count bits of
+ * @return the number of bits set to one in x
+ */
+static inline av_const int av_popcount_c(uint32_t x)
+{
+ x -= (x >> 1) & 0x55555555;
+ x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
+ x = (x + (x >> 4)) & 0x0F0F0F0F;
+ x += x >> 8;
+ return (x + (x >> 16)) & 0x3F;
+}
+
#define MKTAG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
#define MKBETAG(a,b,c,d) ((d) | ((c) << 8) | ((b) << 16) | ((a) << 24))
@@ -345,3 +359,6 @@ static inline av_const int av_ceil_log2_c(int x)
#ifndef av_clipf
# define av_clipf av_clipf_c
#endif
+#ifndef av_popcount
+# define av_popcount av_popcount_c
+#endif
diff --git a/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0039-Add-av_popcount-to-libavutil-common.h-and-bump-minor.patch b/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0039-Add-av_popcount-to-libavutil-common.h-and-bump-minor.patch
new file mode 100644
index 0000000000..387372e792
--- /dev/null
+++ b/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0039-Add-av_popcount-to-libavutil-common.h-and-bump-minor.patch
@@ -0,0 +1,47 @@
+From 348c202ea55f9ec21ba10ffc16dbcd1c3f8d7cfa Mon Sep 17 00:00:00 2001
+From: thardin <thardin@9553f0bf-9b14-0410-a0b8-cfaf0461ba5b>
+Date: Tue, 14 Sep 2010 14:45:43 +0000
+Subject: [PATCH] Add av_popcount() to libavutil/common.h and bump minor version
+
+[anssi@xbmc.org: backported as required for DTS profile exporting patch]
+
+git-svn-id: file:///var/local/repositories/ffmpeg/trunk@25120 9553f0bf-9b14-0410-a0b8-cfaf0461ba5b
+---
+ libavutil/common.h | 17 +++++++++++++++++
+ 2 files changed, 18 insertions(+), 1 deletions(-)
+
+diff --git a/libavutil/common.h b/libavutil/common.h
+index d054f87..6404076 100644
+--- a/libavutil/common.h
++++ b/libavutil/common.h
+@@ -192,6 +192,20 @@ static inline av_const int av_ceil_log2_c(int x)
+ return av_log2((x - 1) << 1);
+ }
+
++/**
++ * Count number of bits set to one in x
++ * @param x value to count bits of
++ * @return the number of bits set to one in x
++ */
++static inline av_const int av_popcount_c(uint32_t x)
++{
++ x -= (x >> 1) & 0x55555555;
++ x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
++ x = (x + (x >> 4)) & 0x0F0F0F0F;
++ x += x >> 8;
++ return (x + (x >> 16)) & 0x3F;
++}
++
+ #define MKTAG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
+ #define MKBETAG(a,b,c,d) ((d) | ((c) << 8) | ((b) << 16) | ((a) << 24))
+
+@@ -351,3 +365,6 @@ static inline av_const int av_ceil_log2_c(int x)
+ #ifndef av_clipf
+ # define av_clipf av_clipf_c
+ #endif
++#ifndef av_popcount
++# define av_popcount av_popcount_c
++#endif
+--
+1.7.3
+
diff --git a/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0040-added-export-DTS-profile-information-in-ffmpeg.patch b/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0040-added-export-DTS-profile-information-in-ffmpeg.patch
new file mode 100644
index 0000000000..37773b2078
--- /dev/null
+++ b/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0040-added-export-DTS-profile-information-in-ffmpeg.patch
@@ -0,0 +1,498 @@
+From da3377e25b0581d3a90a1c103f8df5ef320e7106 Mon Sep 17 00:00:00 2001
+From: Anssi Hannula <anssi@xbmc.org>
+Date: Thu, 6 Jan 2011 20:00:18 +0200
+Subject: [PATCH] added: export DTS profile information in ffmpeg
+
+This allows XBMC to detect DTS-HD types via the profile field.
+
+Patch OK'd by upstream.
+---
+ .../dvdplayer/Codecs/libavcodec/avcodec.h | 6 +
+ .../cores/dvdplayer/Codecs/libavcodec/dca.c | 354 +++++++++++++++++++-
+ .../dvdplayer/Codecs/libavcodec/options.c | 5 +
+ 3 files changed, 362 insertions(+), 3 deletions(-)
+
+diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
+index 705a747..9755603 100644
+--- a/libavcodec/avcodec.h
++++ b/libavcodec/avcodec.h
+@@ -2179,6 +2179,12 @@ typedef struct AVCodecContext {
+ #define FF_PROFILE_AAC_SSR 2
+ #define FF_PROFILE_AAC_LTP 3
+
++#define FF_PROFILE_DTS 20
++#define FF_PROFILE_DTS_ES 30
++#define FF_PROFILE_DTS_96_24 40
++#define FF_PROFILE_DTS_HD_HRA 50
++#define FF_PROFILE_DTS_HD_MA 60
++
+ #define FF_PROFILE_H264_BASELINE 66
+ #define FF_PROFILE_H264_MAIN 77
+ #define FF_PROFILE_H264_EXTENDED 88
+diff --git a/libavcodec/dca.c b/libavcodec/dca.c
+index 7168f41..7c69d2a 100644
+--- a/libavcodec/dca.c
++++ b/libavcodec/dca.c
+@@ -26,6 +26,7 @@
+ #include <stddef.h>
+ #include <stdio.h>
+
++#include "libavutil/common.h"
+ #include "libavutil/intmath.h"
+ #include "libavutil/intreadwrite.h"
+ #include "avcodec.h"
+@@ -63,6 +64,39 @@ enum DCAMode {
+ DCA_4F2R
+ };
+
++/* these are unconfirmed but should be mostly correct */
++enum DCAExSSSpeakerMask {
++ DCA_EXSS_FRONT_CENTER = 0x0001,
++ DCA_EXSS_FRONT_LEFT_RIGHT = 0x0002,
++ DCA_EXSS_SIDE_REAR_LEFT_RIGHT = 0x0004,
++ DCA_EXSS_LFE = 0x0008,
++ DCA_EXSS_REAR_CENTER = 0x0010,
++ DCA_EXSS_FRONT_HIGH_LEFT_RIGHT = 0x0020,
++ DCA_EXSS_REAR_LEFT_RIGHT = 0x0040,
++ DCA_EXSS_FRONT_HIGH_CENTER = 0x0080,
++ DCA_EXSS_OVERHEAD = 0x0100,
++ DCA_EXSS_CENTER_LEFT_RIGHT = 0x0200,
++ DCA_EXSS_WIDE_LEFT_RIGHT = 0x0400,
++ DCA_EXSS_SIDE_LEFT_RIGHT = 0x0800,
++ DCA_EXSS_LFE2 = 0x1000,
++ DCA_EXSS_SIDE_HIGH_LEFT_RIGHT = 0x2000,
++ DCA_EXSS_REAR_HIGH_CENTER = 0x4000,
++ DCA_EXSS_REAR_HIGH_LEFT_RIGHT = 0x8000,
++};
++
++enum DCAExtensionMask {
++ DCA_EXT_CORE = 0x001, ///< core in core substream
++ DCA_EXT_XXCH = 0x002, ///< XXCh channels extension in core substream
++ DCA_EXT_X96 = 0x004, ///< 96/24 extension in core substream
++ DCA_EXT_XCH = 0x008, ///< XCh channel extension in core substream
++ DCA_EXT_EXSS_CORE = 0x010, ///< core in ExSS (extension substream)
++ DCA_EXT_EXSS_XBR = 0x020, ///< extended bitrate extension in ExSS
++ DCA_EXT_EXSS_XXCH = 0x040, ///< XXCh channels extension in ExSS
++ DCA_EXT_EXSS_X96 = 0x080, ///< 96/24 extension in ExSS
++ DCA_EXT_EXSS_LBR = 0x100, ///< low bitrate component in ExSS
++ DCA_EXT_EXSS_XLL = 0x200, ///< lossless extension in ExSS
++};
++
+ /* Tables for mapping dts channel configurations to libavcodec multichannel api.
+ * Some compromises have been made for special configurations. Most configurations
+ * are never used so complete accuracy is not needed.
+@@ -182,6 +216,7 @@ static const int8_t dca_channel_reorder_nolfe_xch[][9] = {
+ #define HEADER_SIZE 14
+
+ #define DCA_MAX_FRAME_SIZE 16384
++#define DCA_MAX_EXSS_HEADER_SIZE 4096
+
+ /** Bit allocation */
+ typedef struct {
+@@ -279,7 +314,7 @@ typedef struct {
+ DECLARE_ALIGNED(16, float, samples)[(DCA_PRIM_CHANNELS_MAX+1)*256];
+ const float *samples_chanptr[DCA_PRIM_CHANNELS_MAX+1];
+
+- uint8_t dca_buffer[DCA_MAX_FRAME_SIZE];
++ uint8_t dca_buffer[DCA_MAX_FRAME_SIZE + DCA_MAX_EXSS_HEADER_SIZE];
+ int dca_buffer_size; ///< how much data is in the dca_buffer
+
+ const int8_t* channel_order_tab; ///< channel reordering table, lfe and non lfe
+@@ -292,6 +327,18 @@ typedef struct {
+ int xch_present;
+ int xch_base_channel; ///< index of first (only) channel containing XCH data
+
++ /* Other detected extensions in the core substream */
++ int xxch_present;
++ int x96_present;
++
++ /* ExSS header parser */
++ int static_fields; ///< static fields present
++ int mix_metadata; ///< mixing metadata present
++ int num_mix_configs; ///< number of mix out configurations
++ int mix_config_num_ch[4]; ///< number of channels in each mix out configuration
++
++ int profile;
++
+ int debug_flag; ///< used for suppressing repeated error messages output
+ DSPContext dsp;
+ FFTContext imdct;
+@@ -1251,6 +1298,278 @@ static int dca_convert_bitstream(const uint8_t * src, int src_size, uint8_t * ds
+ }
+
+ /**
++ * Return the number of channels in an ExSS speaker mask (HD)
++ */
++static int dca_exss_mask2count(int mask)
++{
++ /* count bits that mean speaker pairs twice */
++ return av_popcount(mask)
++ + av_popcount(mask & (
++ DCA_EXSS_CENTER_LEFT_RIGHT
++ | DCA_EXSS_FRONT_LEFT_RIGHT
++ | DCA_EXSS_FRONT_HIGH_LEFT_RIGHT
++ | DCA_EXSS_WIDE_LEFT_RIGHT
++ | DCA_EXSS_SIDE_LEFT_RIGHT
++ | DCA_EXSS_SIDE_HIGH_LEFT_RIGHT
++ | DCA_EXSS_SIDE_REAR_LEFT_RIGHT
++ | DCA_EXSS_REAR_LEFT_RIGHT
++ | DCA_EXSS_REAR_HIGH_LEFT_RIGHT
++ ));
++}
++
++/**
++ * Skip mixing coefficients of a single mix out configuration (HD)
++ */
++static void dca_exss_skip_mix_coeffs(GetBitContext *gb, int channels, int out_ch)
++{
++ for (int i = 0; i < channels; i++) {
++ int mix_map_mask = get_bits(gb, out_ch);
++ int num_coeffs = av_popcount(mix_map_mask);
++ skip_bits_long(gb, num_coeffs * 6);
++ }
++}
++
++/**
++ * Parse extension substream asset header (HD)
++ */
++static int dca_exss_parse_asset_header(DCAContext *s)
++{
++ int header_pos = get_bits_count(&s->gb);
++ int header_size;
++ int channels;
++ int embedded_stereo = 0;
++ int embedded_6ch = 0;
++ int drc_code_present;
++ int extensions_mask;
++ int i, j;
++
++ if (get_bits_left(&s->gb) < 16)
++ return -1;
++
++ /* We will parse just enough to get to the extensions bitmask with which
++ * we can set the profile value. */
++
++ header_size = get_bits(&s->gb, 9) + 1;
++ skip_bits(&s->gb, 3); // asset index
++
++ if (s->static_fields) {
++ if (get_bits1(&s->gb))
++ skip_bits(&s->gb, 4); // asset type descriptor
++ if (get_bits1(&s->gb))
++ skip_bits_long(&s->gb, 24); // language descriptor
++
++ if (get_bits1(&s->gb)) {
++ /* How can one fit 1024 bytes of text here if the maximum value
++ * for the asset header size field above was 512 bytes? */
++ int text_length = get_bits(&s->gb, 10) + 1;
++ if (get_bits_left(&s->gb) < text_length * 8)
++ return -1;
++ skip_bits_long(&s->gb, text_length * 8); // info text
++ }
++
++ skip_bits(&s->gb, 5); // bit resolution - 1
++ skip_bits(&s->gb, 4); // max sample rate code
++ channels = get_bits(&s->gb, 8) + 1;
++
++ if (get_bits1(&s->gb)) { // 1-to-1 channels to speakers
++ int spkr_remap_sets;
++ int spkr_mask_size = 16;
++ int num_spkrs[7];
++
++ if (channels > 2)
++ embedded_stereo = get_bits1(&s->gb);
++ if (channels > 6)
++ embedded_6ch = get_bits1(&s->gb);
++
++ if (get_bits1(&s->gb)) {
++ spkr_mask_size = (get_bits(&s->gb, 2) + 1) << 2;
++ skip_bits(&s->gb, spkr_mask_size); // spkr activity mask
++ }
++
++ spkr_remap_sets = get_bits(&s->gb, 3);
++
++ for (i = 0; i < spkr_remap_sets; i++) {
++ /* std layout mask for each remap set */
++ num_spkrs[i] = dca_exss_mask2count(get_bits(&s->gb, spkr_mask_size));
++ }
++
++ for (i = 0; i < spkr_remap_sets; i++) {
++ int num_dec_ch_remaps = get_bits(&s->gb, 5) + 1;
++ if (get_bits_left(&s->gb) < 0)
++ return -1;
++
++ for (j = 0; j < num_spkrs[i]; j++) {
++ int remap_dec_ch_mask = get_bits_long(&s->gb, num_dec_ch_remaps);
++ int num_dec_ch = av_popcount(remap_dec_ch_mask);
++ skip_bits_long(&s->gb, num_dec_ch * 5); // remap codes
++ }
++ }
++
++ } else {
++ skip_bits(&s->gb, 3); // representation type
++ }
++ }
++
++ drc_code_present = get_bits1(&s->gb);
++ if (drc_code_present)
++ get_bits(&s->gb, 8); // drc code
++
++ if (get_bits1(&s->gb))
++ skip_bits(&s->gb, 5); // dialog normalization code
++
++ if (drc_code_present && embedded_stereo)
++ get_bits(&s->gb, 8); // drc stereo code
++
++ if (s->mix_metadata && get_bits1(&s->gb)) {
++ skip_bits(&s->gb, 1); // external mix
++ skip_bits(&s->gb, 6); // post mix gain code
++
++ if (get_bits(&s->gb, 2) != 3) // mixer drc code
++ skip_bits(&s->gb, 3); // drc limit
++ else
++ skip_bits(&s->gb, 8); // custom drc code
++
++ if (get_bits1(&s->gb)) // channel specific scaling
++ for (i = 0; i < s->num_mix_configs; i++)
++ skip_bits_long(&s->gb, s->mix_config_num_ch[i] * 6); // scale codes
++ else
++ skip_bits_long(&s->gb, s->num_mix_configs * 6); // scale codes
++
++ for (i = 0; i < s->num_mix_configs; i++) {
++ if (get_bits_left(&s->gb) < 0)
++ return -1;
++ dca_exss_skip_mix_coeffs(&s->gb, channels, s->mix_config_num_ch[i]);
++ if (embedded_6ch)
++ dca_exss_skip_mix_coeffs(&s->gb, 6, s->mix_config_num_ch[i]);
++ if (embedded_stereo)
++ dca_exss_skip_mix_coeffs(&s->gb, 2, s->mix_config_num_ch[i]);
++ }
++ }
++
++ switch (get_bits(&s->gb, 2)) {
++ case 0: extensions_mask = get_bits(&s->gb, 12); break;
++ case 1: extensions_mask = DCA_EXT_EXSS_XLL; break;
++ case 2: extensions_mask = DCA_EXT_EXSS_LBR; break;
++ case 3: extensions_mask = 0; /* aux coding */ break;
++ }
++
++ /* not parsed further, we were only interested in the extensions mask */
++
++ if (get_bits_left(&s->gb) < 0)
++ return -1;
++
++ if (get_bits_count(&s->gb) - header_pos > header_size * 8) {
++ av_log(s->avctx, AV_LOG_WARNING, "Asset header size mismatch.\n");
++ return -1;
++ }
++ skip_bits_long(&s->gb, header_pos + header_size * 8 - get_bits_count(&s->gb));
++
++ if (extensions_mask & DCA_EXT_EXSS_XLL)
++ s->profile = FF_PROFILE_DTS_HD_MA;
++ else if (extensions_mask & DCA_EXT_EXSS_XBR)
++ s->profile = FF_PROFILE_DTS_HD_HRA;
++ else if (extensions_mask & DCA_EXT_EXSS_X96)
++ s->profile = FF_PROFILE_DTS_96_24;
++ else if (extensions_mask & DCA_EXT_EXSS_XXCH)
++ s->profile = FFMAX(s->profile, FF_PROFILE_DTS_ES);
++
++ if (!(extensions_mask & DCA_EXT_CORE))
++ av_log(s->avctx, AV_LOG_WARNING, "DTS core detection mismatch.\n");
++ if (!!(extensions_mask & DCA_EXT_XCH) != s->xch_present)
++ av_log(s->avctx, AV_LOG_WARNING, "DTS XCh detection mismatch.\n");
++ if (!!(extensions_mask & DCA_EXT_XXCH) != s->xxch_present)
++ av_log(s->avctx, AV_LOG_WARNING, "DTS XXCh detection mismatch.\n");
++ if (!!(extensions_mask & DCA_EXT_X96) != s->x96_present)
++ av_log(s->avctx, AV_LOG_WARNING, "DTS X96 detection mismatch.\n");
++
++ return 0;
++}
++
++/**
++ * Parse extension substream header (HD)
++ */
++static void dca_exss_parse_header(DCAContext *s)
++{
++ int ss_index;
++ int blownup;
++ int header_size;
++ int hd_size;
++ int num_audiop = 1;
++ int num_assets = 1;
++ int active_ss_mask[8];
++ int i, j;
++
++ if (get_bits_left(&s->gb) < 52)
++ return;
++
++ skip_bits(&s->gb, 8); // user data
++ ss_index = get_bits(&s->gb, 2);
++
++ blownup = get_bits1(&s->gb);
++ header_size = get_bits(&s->gb, 8 + 4 * blownup) + 1;
++ hd_size = get_bits_long(&s->gb, 16 + 4 * blownup) + 1;
++
++ s->static_fields = get_bits1(&s->gb);
++ if (s->static_fields) {
++ skip_bits(&s->gb, 2); // reference clock code
++ skip_bits(&s->gb, 3); // frame duration code
++
++ if (get_bits1(&s->gb))
++ skip_bits_long(&s->gb, 36); // timestamp
++
++ /* a single stream can contain multiple audio assets that can be
++ * combined to form multiple audio presentations */
++
++ num_audiop = get_bits(&s->gb, 3) + 1;
++ if (num_audiop > 1) {
++ av_log_ask_for_sample(s->avctx, "Multiple DTS-HD audio presentations.");
++ /* ignore such streams for now */
++ return;
++ }
++
++ num_assets = get_bits(&s->gb, 3) + 1;
++ if (num_assets > 1) {
++ av_log_ask_for_sample(s->avctx, "Multiple DTS-HD audio assets.");
++ /* ignore such streams for now */
++ return;
++ }
++
++ for (i = 0; i < num_audiop; i++)
++ active_ss_mask[i] = get_bits(&s->gb, ss_index + 1);
++
++ for (i = 0; i < num_audiop; i++)
++ for (j = 0; j <= ss_index; j++)
++ if (active_ss_mask[i] & (1 << j))
++ skip_bits(&s->gb, 8); // active asset mask
++
++ s->mix_metadata = get_bits1(&s->gb);
++ if (s->mix_metadata) {
++ int mix_out_mask_size;
++
++ skip_bits(&s->gb, 2); // adjustment level
++ mix_out_mask_size = (get_bits(&s->gb, 2) + 1) << 2;
++ s->num_mix_configs = get_bits(&s->gb, 2) + 1;
++
++ for (i = 0; i < s->num_mix_configs; i++) {
++ int mix_out_mask = get_bits(&s->gb, mix_out_mask_size);
++ s->mix_config_num_ch[i] = dca_exss_mask2count(mix_out_mask);
++ }
++ }
++ }
++
++ for (i = 0; i < num_assets; i++)
++ skip_bits_long(&s->gb, 16 + 4 * blownup); // asset size
++
++ for (i = 0; i < num_assets; i++) {
++ if (dca_exss_parse_asset_header(s))
++ return;
++ }
++
++ /* not parsed further, we were only interested in the extensions mask
++ * from the asset header */
++}
++
++/**
+ * Main frame decoding function
+ * FIXME add arguments
+ */
+@@ -1267,10 +1586,15 @@ static int dca_decode_frame(AVCodecContext * avctx,
+ int16_t *samples = data;
+ DCAContext *s = avctx->priv_data;
+ int channels;
++ int core_ss_end;
+
+
+ s->xch_present = 0;
+- s->dca_buffer_size = dca_convert_bitstream(buf, buf_size, s->dca_buffer, DCA_MAX_FRAME_SIZE);
++ s->x96_present = 0;
++ s->xxch_present = 0;
++
++ s->dca_buffer_size = dca_convert_bitstream(buf, buf_size, s->dca_buffer,
++ DCA_MAX_FRAME_SIZE + DCA_MAX_EXSS_HEADER_SIZE);
+ if (s->dca_buffer_size == -1) {
+ av_log(avctx, AV_LOG_ERROR, "Not a valid DCA frame\n");
+ return -1;
+@@ -1287,6 +1611,8 @@ static int dca_decode_frame(AVCodecContext * avctx,
+ avctx->bit_rate = s->bit_rate;
+ avctx->frame_size = s->sample_blocks * 32;
+
++ s->profile = FF_PROFILE_DTS;
++
+ for (i = 0; i < (s->sample_blocks / 8); i++) {
+ dca_decode_block(s, 0, i);
+ }
+@@ -1297,7 +1623,9 @@ static int dca_decode_frame(AVCodecContext * avctx,
+ /* extensions start at 32-bit boundaries into bitstream */
+ skip_bits_long(&s->gb, (-get_bits_count(&s->gb)) & 31);
+
+- while(get_bits_left(&s->gb) >= 32) {
++ core_ss_end = FFMIN(s->frame_size, s->dca_buffer_size) * 8;
++
++ while(core_ss_end - get_bits_count(&s->gb) >= 32) {
+ uint32_t bits = get_bits_long(&s->gb, 32);
+
+ switch(bits) {
+@@ -1315,6 +1643,8 @@ static int dca_decode_frame(AVCodecContext * avctx,
+ /* skip length-to-end-of-frame field for the moment */
+ skip_bits(&s->gb, 10);
+
++ s->profile = FFMAX(s->profile, FF_PROFILE_DTS_ES);
++
+ /* extension amode should == 1, number of channels in extension */
+ /* AFAIK XCh is not used for more channels */
+ if ((ext_amode = get_bits(&s->gb, 4)) != 1) {
+@@ -1333,16 +1663,34 @@ static int dca_decode_frame(AVCodecContext * avctx,
+ s->xch_present = 1;
+ break;
+ }
++ case 0x47004a03:
++ /* XXCh: extended channels */
++ /* usually found either in core or HD part in DTS-HD HRA streams,
++ * but not in DTS-ES which contains XCh extensions instead */
++ s->xxch_present = 1;
++ s->profile = FFMAX(s->profile, FF_PROFILE_DTS_ES);
++ break;
++
+ case 0x1d95f262:
+ av_log(avctx, AV_LOG_DEBUG, "Possible X96 extension found at %d bits\n", get_bits_count(&s->gb));
+ av_log(avctx, AV_LOG_DEBUG, "FSIZE96 = %d bytes\n", get_bits(&s->gb, 12)+1);
+ av_log(avctx, AV_LOG_DEBUG, "REVNO = %d\n", get_bits(&s->gb, 4));
++
++ s->x96_present = 1;
++ s->profile = FFMAX(s->profile, FF_PROFILE_DTS_96_24);
+ break;
+ }
+
+ skip_bits_long(&s->gb, (-get_bits_count(&s->gb)) & 31);
+ }
+
++ /* check for ExSS (HD part) */
++ if (s->dca_buffer_size - s->frame_size > 32
++ && get_bits_long(&s->gb, 32) == DCA_HD_MARKER)
++ dca_exss_parse_header(s);
++
++ avctx->profile = s->profile;
++
+ channels = s->prim_channels + !!s->lfe;
+
+ if (s->amode<16) {
+diff --git a/libavcodec/options.c b/libavcodec/options.c
+index 744957d..c59e92b 100644
+--- a/libavcodec/options.c
++++ b/libavcodec/options.c
+@@ -331,6 +331,11 @@ static const AVOption options[]={
+ {"aac_low", NULL, 0, FF_OPT_TYPE_CONST, FF_PROFILE_AAC_LOW, INT_MIN, INT_MAX, A|E, "profile"},
+ {"aac_ssr", NULL, 0, FF_OPT_TYPE_CONST, FF_PROFILE_AAC_SSR, INT_MIN, INT_MAX, A|E, "profile"},
+ {"aac_ltp", NULL, 0, FF_OPT_TYPE_CONST, FF_PROFILE_AAC_LTP, INT_MIN, INT_MAX, A|E, "profile"},
++{"dts", NULL, 0, FF_OPT_TYPE_CONST, FF_PROFILE_DTS, INT_MIN, INT_MAX, A|E, "profile"},
++{"dts_es", NULL, 0, FF_OPT_TYPE_CONST, FF_PROFILE_DTS_ES, INT_MIN, INT_MAX, A|E, "profile"},
++{"dts_96_24", NULL, 0, FF_OPT_TYPE_CONST, FF_PROFILE_DTS_96_24, INT_MIN, INT_MAX, A|E, "profile"},
++{"dts_hd_hra", NULL, 0, FF_OPT_TYPE_CONST, FF_PROFILE_DTS_HD_HRA, INT_MIN, INT_MAX, A|E, "profile"},
++{"dts_hd_ma", NULL, 0, FF_OPT_TYPE_CONST, FF_PROFILE_DTS_HD_MA, INT_MIN, INT_MAX, A|E, "profile"},
+ {"level", NULL, OFFSET(level), FF_OPT_TYPE_INT, FF_LEVEL_UNKNOWN, INT_MIN, INT_MAX, V|A|E, "level"},
+ {"unknown", NULL, 0, FF_OPT_TYPE_CONST, FF_LEVEL_UNKNOWN, INT_MIN, INT_MAX, V|A|E, "level"},
+ {"lowres", "decode at 1= 1/2, 2=1/4, 3=1/8 resolutions", OFFSET(lowres), FF_OPT_TYPE_INT, 0, 0, INT_MAX, V|D},
+--
+1.7.3
+
diff --git a/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0041-Add-av_get_profile_name-to-get-profile-names.patch b/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0041-Add-av_get_profile_name-to-get-profile-names.patch
new file mode 100644
index 0000000000..9aba16463f
--- /dev/null
+++ b/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0041-Add-av_get_profile_name-to-get-profile-names.patch
@@ -0,0 +1,84 @@
+From 060ec0a8294d912f694cf48546f1543805f83a48 Mon Sep 17 00:00:00 2001
+From: Anssi Hannula <anssi.hannula@iki.fi>
+Date: Fri, 7 Jan 2011 22:27:26 +0000
+Subject: [PATCH] Add av_get_profile_name() to get profile names.
+
+Patch by Anssi Hannula, anssi d hannula a iki d fi
+
+Originally committed as revision 26259 to svn://svn.ffmpeg.org/ffmpeg/trunk
+---
+ doc/APIchanges | 3 +++
+ libavcodec/avcodec.h | 22 ++++++++++++++++++++--
+ libavcodec/utils.c | 13 +++++++++++++
+ 3 files changed, 36 insertions(+), 2 deletions(-)
+
+diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
+index 7850e1d..309edae 100644
+--- a/libavcodec/avcodec.h
++++ b/libavcodec/avcodec.h
+@@ -2794,6 +2794,14 @@ typedef struct AVCodecContext {
+ } AVCodecContext;
+
+ /**
++ * AVProfile.
++ */
++typedef struct AVProfile {
++ int profile;
++ const char *name; ///< short name for the profile
++} AVProfile;
++
++/**
+ * AVCodec.
+ */
+ typedef struct AVCodec {
+@@ -2834,6 +2842,7 @@ typedef struct AVCodec {
+ const enum SampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1
+ const int64_t *channel_layouts; ///< array of support channel layouts, or NULL if unknown. array is terminated by 0
+ uint8_t max_lowres; ///< maximum value for lowres supported by the decoder
++ const AVProfile *profiles; ///< array of recognized profiles, or NULL if unknown, array is terminated by {FF_PROFILE_UNKNOWN}
+ } AVCodec;
+
+ /**
+@@ -3394,6 +3403,15 @@ AVCodec *avcodec_find_decoder_by_name(const char *name);
+ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode);
+
+ /**
++ * Return a name for the specified profile, if available.
++ *
++ * @param codec the codec that is searched for the given profile
++ * @param profile the profile value for which a name is requested
++ * @return A name for the profile if found, NULL otherwise.
++ */
++const char *av_get_profile_name(const AVCodec *codec, int profile);
++
++/**
+ * Set the fields of the given AVCodecContext to default values.
+ *
+ * @param s The AVCodecContext of which the fields should be set to default values.
+diff --git a/libavcodec/utils.c b/libavcodec/utils.c
+index ce74735..c11e4f5 100644
+--- a/libavcodec/utils.c
++++ b/libavcodec/utils.c
+@@ -966,6 +966,19 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
+ }
+ }
+
++const char *av_get_profile_name(const AVCodec *codec, int profile)
++{
++ const AVProfile *p;
++ if (profile == FF_PROFILE_UNKNOWN || !codec->profiles)
++ return NULL;
++
++ for (p = codec->profiles; p->profile != FF_PROFILE_UNKNOWN; p++)
++ if (p->profile == profile)
++ return p->name;
++
++ return NULL;
++}
++
+ unsigned avcodec_version( void )
+ {
+ return LIBAVCODEC_VERSION_INT;
+--
+1.7.3
+
diff --git a/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0042-Show-profile-in-avcodec_string.patch b/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0042-Show-profile-in-avcodec_string.patch
new file mode 100644
index 0000000000..891a193797
--- /dev/null
+++ b/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0042-Show-profile-in-avcodec_string.patch
@@ -0,0 +1,55 @@
+From 2a81f4bde50f731074c1be7368128de49f78925a Mon Sep 17 00:00:00 2001
+From: Anssi Hannula <anssi.hannula@iki.fi>
+Date: Sat, 8 Jan 2011 09:23:25 +0000
+Subject: [PATCH] Show profile in avcodec_string().
+
+Patch by Anssi Hannula, anssi d hannula a iki d fi
+
+Originally committed as revision 26264 to svn://svn.ffmpeg.org/ffmpeg/trunk
+---
+ libavcodec/utils.c | 8 ++++++++
+ 1 files changed, 8 insertions(+), 0 deletions(-)
+
+diff --git a/libavcodec/utils.c b/libavcodec/utils.c
+index 0295147..8cc9299 100644
+--- a/libavcodec/utils.c
++++ b/libavcodec/utils.c
+@@ -871,6 +871,7 @@ size_t av_get_codec_tag_string(char *buf, size_t buf_size, unsigned int codec_ta
+ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
+ {
+ const char *codec_name;
++ const char *profile = NULL;
+ AVCodec *p;
+ char buf1[32];
+ int bitrate;
+@@ -883,6 +884,7 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
+
+ if (p) {
+ codec_name = p->name;
++ profile = av_get_profile_name(p, enc->profile);
+ } else if (enc->codec_id == CODEC_ID_MPEG2TS) {
+ /* fake mpeg2 transport stream codec (currently not
+ registered) */
+@@ -902,6 +904,9 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
+ snprintf(buf, buf_size,
+ "Video: %s%s",
+ codec_name, enc->mb_decision ? " (hq)" : "");
++ if (profile)
++ snprintf(buf + strlen(buf), buf_size - strlen(buf),
++ " (%s)", profile);
+ if (enc->pix_fmt != PIX_FMT_NONE) {
+ snprintf(buf + strlen(buf), buf_size - strlen(buf),
+ ", %s",
+@@ -937,6 +942,9 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
+ snprintf(buf, buf_size,
+ "Audio: %s",
+ codec_name);
++ if (profile)
++ snprintf(buf + strlen(buf), buf_size - strlen(buf),
++ " (%s)", profile);
+ if (enc->sample_rate) {
+ snprintf(buf + strlen(buf), buf_size - strlen(buf),
+ ", %d Hz", enc->sample_rate);
+--
+1.7.3
+
diff --git a/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0043-h264-add-profile-names-for-the-existing-defines.patch b/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0043-h264-add-profile-names-for-the-existing-defines.patch
new file mode 100644
index 0000000000..3a10d41bfb
--- /dev/null
+++ b/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0043-h264-add-profile-names-for-the-existing-defines.patch
@@ -0,0 +1,51 @@
+From 306bd2d20ada5782ea28037072e9d4f0cc9dae90 Mon Sep 17 00:00:00 2001
+From: Anssi Hannula <anssi.hannula@iki.fi>
+Date: Fri, 7 Jan 2011 18:59:17 +0200
+Subject: [PATCH 43/46] h264: add profile names for the existing defines
+
+Submitted upstream.
+
+---
+ libavcodec/h264.c | 13 +++++++++++++
+ 1 files changed, 13 insertions(+), 0 deletions(-)
+
+diff --git a/libavcodec/h264.c b/libavcodec/h264.c
+index 40dc276..04caa9f 100644
+--- a/libavcodec/h264.c
++++ b/libavcodec/h264.c
+@@ -3354,6 +3354,17 @@ av_cold int ff_h264_decode_end(AVCodecContext *avctx)
+ return 0;
+ }
+
++static const AVProfile profiles[] = {
++ { FF_PROFILE_H264_BASELINE, "Baseline" },
++ { FF_PROFILE_H264_MAIN, "Main" },
++ { FF_PROFILE_H264_EXTENDED, "Extended" },
++ { FF_PROFILE_H264_HIGH, "High" },
++ { FF_PROFILE_H264_HIGH_10, "High 10" },
++ { FF_PROFILE_H264_HIGH_422, "High 4:2:2" },
++ { FF_PROFILE_H264_HIGH_444, "High 4:4:4" },
++ { FF_PROFILE_H264_CAVLC_444, "CAVLC 4:4:4" },
++ { FF_PROFILE_UNKNOWN },
++};
+
+ AVCodec h264_decoder = {
+ "h264",
+@@ -3367,6 +3378,7 @@ AVCodec h264_decoder = {
+ /*CODEC_CAP_DRAW_HORIZ_BAND |*/ CODEC_CAP_DR1 | CODEC_CAP_DELAY,
+ .flush= flush_dpb,
+ .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"),
++ .profiles = profiles,
+ };
+
+ #if CONFIG_H264_VDPAU_DECODER
+@@ -3383,5 +3395,6 @@ AVCodec h264_vdpau_decoder = {
+ .flush= flush_dpb,
+ .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (VDPAU acceleration)"),
+ .pix_fmts = (const enum PixelFormat[]){PIX_FMT_VDPAU_H264, PIX_FMT_NONE},
++ .profiles = profiles,
+ };
+ #endif
+--
+1.7.3
+
diff --git a/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0044-aacenc-add-recognized-profiles-array.patch b/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0044-aacenc-add-recognized-profiles-array.patch
new file mode 100644
index 0000000000..72398832fa
--- /dev/null
+++ b/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0044-aacenc-add-recognized-profiles-array.patch
@@ -0,0 +1,36 @@
+From 5a25200ef7dca766d66e35df35adf4fc519a6229 Mon Sep 17 00:00:00 2001
+From: Anssi Hannula <anssi.hannula@iki.fi>
+Date: Fri, 21 Jan 2011 20:44:02 +0200
+Subject: [PATCH 44/46] aacenc: add recognized profiles array
+
+Submitted upstream.
+
+---
+ libavcodec/aacenc.c | 6 ++++++
+ 1 files changed, 6 insertions(+), 0 deletions(-)
+
+diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c
+index c52ffa0..762e0c8 100644
+--- a/libavcodec/aacenc.c
++++ b/libavcodec/aacenc.c
+@@ -636,6 +636,11 @@ static av_cold int aac_encode_end(AVCodecContext *avctx)
+ return 0;
+ }
+
++static const AVProfile profiles[] = {
++ { FF_PROFILE_AAC_LOW, "Low" },
++ { FF_PROFILE_UNKNOWN },
++};
++
+ AVCodec aac_encoder = {
+ "aac",
+ AVMEDIA_TYPE_AUDIO,
+@@ -647,4 +652,5 @@ AVCodec aac_encoder = {
+ .capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
+ .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
+ .long_name = NULL_IF_CONFIG_SMALL("Advanced Audio Coding"),
++ .profiles = profiles,
+ };
+--
+1.7.3
+
diff --git a/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0045-libfaac-add-recognized-profiles-array.patch b/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0045-libfaac-add-recognized-profiles-array.patch
new file mode 100644
index 0000000000..2312624751
--- /dev/null
+++ b/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0045-libfaac-add-recognized-profiles-array.patch
@@ -0,0 +1,39 @@
+From 8a30526df1c047d946d015167fbde54a5696384e Mon Sep 17 00:00:00 2001
+From: Anssi Hannula <anssi.hannula@iki.fi>
+Date: Fri, 21 Jan 2011 20:45:56 +0200
+Subject: [PATCH 45/46] libfaac: add recognized profiles array
+
+Submitted upstream.
+
+---
+ libavcodec/libfaac.c | 9 +++++++++
+ 1 files changed, 9 insertions(+), 0 deletions(-)
+
+diff --git a/libavcodec/libfaac.c b/libavcodec/libfaac.c
+index b220b17..b1bf54d 100644
+--- a/libavcodec/libfaac.c
++++ b/libavcodec/libfaac.c
+@@ -145,6 +145,14 @@ static av_cold int Faac_encode_close(AVCodecContext *avctx)
+ return 0;
+ }
+
++static const AVProfile profiles[] = {
++ { FF_PROFILE_AAC_MAIN, "Main" },
++ { FF_PROFILE_AAC_LOW, "Low" },
++ { FF_PROFILE_AAC_SSR, "SSR" },
++ { FF_PROFILE_AAC_LTP, "LTP" },
++ { FF_PROFILE_UNKNOWN },
++};
++
+ AVCodec libfaac_encoder = {
+ "libfaac",
+ AVMEDIA_TYPE_AUDIO,
+@@ -155,4 +163,5 @@ AVCodec libfaac_encoder = {
+ Faac_encode_close,
+ .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
+ .long_name = NULL_IF_CONFIG_SMALL("libfaac AAC (Advanced Audio Codec)"),
++ .profiles = profiles,
+ };
+--
+1.7.3
+
diff --git a/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0046-dca-add-profile-names.patch b/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0046-dca-add-profile-names.patch
new file mode 100644
index 0000000000..a95ba5188e
--- /dev/null
+++ b/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0046-dca-add-profile-names.patch
@@ -0,0 +1,40 @@
+From 6d7a0b722e98656cd769a972be6b61c03179d7d8 Mon Sep 17 00:00:00 2001
+From: Anssi Hannula <anssi.hannula@iki.fi>
+Date: Fri, 21 Jan 2011 20:49:10 +0200
+Subject: [PATCH 46/46] dca: add profile names
+
+Submitted and ok'd upstream.
+
+---
+ libavcodec/dca.c | 10 ++++++++++
+ 1 files changed, 10 insertions(+), 0 deletions(-)
+
+diff --git a/libavcodec/dca.c b/libavcodec/dca.c
+index bc099e1..48b79e8 100644
+--- a/libavcodec/dca.c
++++ b/libavcodec/dca.c
+@@ -1869,6 +1869,15 @@ static av_cold int dca_decode_end(AVCodecContext * avctx)
+ return 0;
+ }
+
++static const AVProfile profiles[] = {
++ { FF_PROFILE_DTS, "DTS" },
++ { FF_PROFILE_DTS_ES, "DTS-ES" },
++ { FF_PROFILE_DTS_96_24, "DTS 96/24" },
++ { FF_PROFILE_DTS_HD_HRA, "DTS-HD HRA" },
++ { FF_PROFILE_DTS_HD_MA, "DTS-HD MA" },
++ { FF_PROFILE_UNKNOWN },
++};
++
+ AVCodec dca_decoder = {
+ .name = "dca",
+ .type = AVMEDIA_TYPE_AUDIO,
+@@ -1879,4 +1888,5 @@ AVCodec dca_decoder = {
+ .decode = dca_decode_frame,
+ .close = dca_decode_end,
+ .long_name = NULL_IF_CONFIG_SMALL("DCA (DTS Coherent Acoustics)"),
++ .profiles = profiles,
+ };
+--
+1.7.3
+
diff --git a/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0047-dca-consider-a-stream-with-XXCh-X96-in-ExSS-as-DTS-H.patch b/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0047-dca-consider-a-stream-with-XXCh-X96-in-ExSS-as-DTS-H.patch
new file mode 100644
index 0000000000..9eea7b9988
--- /dev/null
+++ b/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0047-dca-consider-a-stream-with-XXCh-X96-in-ExSS-as-DTS-H.patch
@@ -0,0 +1,37 @@
+From 572f32953b27328c6ba504073d229de987b97d60 Mon Sep 17 00:00:00 2001
+From: Anssi Hannula <anssi.hannula@iki.fi>
+Date: Fri, 21 Jan 2011 21:49:15 +0200
+Subject: [PATCH] dca: consider a stream with XXCh/X96 in ExSS as DTS-HD HRA
+
+DTS-HD HRA streams do not always have an XBR extension in the extension
+substream. Instead they can have only XXCh and X96 extensions in
+there and still be considered DTS-HD HRA.
+
+This is also confirmed with Onkyo TX-SR607 receiver which recognizes
+such a stream as HiRes Audio.
+---
+ libavcodec/dca.c | 7 ++-----
+ 1 files changed, 2 insertions(+), 5 deletions(-)
+
+diff --git a/libavcodec/dca.c b/libavcodec/dca.c
+index 48b79e8..90b470f 100644
+--- a/libavcodec/dca.c
++++ b/libavcodec/dca.c
+@@ -1501,12 +1501,9 @@ static int dca_exss_parse_asset_header(DCAContext *s)
+
+ if (extensions_mask & DCA_EXT_EXSS_XLL)
+ s->profile = FF_PROFILE_DTS_HD_MA;
+- else if (extensions_mask & DCA_EXT_EXSS_XBR)
++ else if (extensions_mask & (DCA_EXT_EXSS_XBR | DCA_EXT_EXSS_X96 |
++ DCA_EXT_EXSS_XXCH))
+ s->profile = FF_PROFILE_DTS_HD_HRA;
+- else if (extensions_mask & DCA_EXT_EXSS_X96)
+- s->profile = FF_PROFILE_DTS_96_24;
+- else if (extensions_mask & DCA_EXT_EXSS_XXCH)
+- s->profile = FFMAX(s->profile, FF_PROFILE_DTS_ES);
+
+ if (!(extensions_mask & DCA_EXT_CORE))
+ av_log(s->avctx, AV_LOG_WARNING, "DTS core detection mismatch.\n");
+--
+1.7.3
+
diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.cpp
index 9a37bac0a0..a84a8a8496 100644
--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.cpp
+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.cpp
@@ -33,7 +33,17 @@ void CDemuxStreamAudio::GetStreamType(std::string& strInfo)
char sInfo[64];
if (codec == CODEC_ID_AC3) strcpy(sInfo, "AC3 ");
- else if (codec == CODEC_ID_DTS) strcpy(sInfo, "DTS ");
+ else if (codec == CODEC_ID_DTS)
+ {
+#ifdef FF_PROFILE_DTS_HD_MA
+ if (profile == FF_PROFILE_DTS_HD_MA)
+ strcpy(sInfo, "DTS-HD MA ");
+ else if (profile == FF_PROFILE_DTS_HD_HRA)
+ strcpy(sInfo, "DTS-HD HRA ");
+ else
+#endif
+ strcpy(sInfo, "DTS ");
+ }
else if (codec == CODEC_ID_MP2) strcpy(sInfo, "MP2 ");
else strcpy(sInfo, "");
diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h
index fe9fa59f42..c7ef328a7a 100644
--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h
+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h
@@ -32,6 +32,7 @@ class CDVDInputStream;
#endif
#ifndef _LINUX
enum CodecID;
+#include <libavcodec/avcodec.h>
#else
extern "C" {
#if (defined USE_EXTERNAL_FFMPEG)
@@ -80,6 +81,7 @@ public:
iPhysicalId = 0;
codec = (CodecID)0; // CODEC_ID_NONE
codec_fourcc = 0;
+ profile = FF_PROFILE_UNKNOWN;
type = STREAM_NONE;
source = STREAM_SOURCE_NONE;
iDuration = 0;
@@ -107,6 +109,7 @@ public:
int iPhysicalId; // id
CodecID codec;
unsigned int codec_fourcc; // if available
+ int profile;
StreamType type;
int source;
diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
index 1ab70ea1d1..4060488aea 100644
--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
@@ -1083,6 +1083,7 @@ void CDVDDemuxFFmpeg::AddStream(int iId)
m_streams[iId]->codec = pStream->codec->codec_id;
m_streams[iId]->codec_fourcc = pStream->codec->codec_tag;
+ m_streams[iId]->profile = pStream->codec->profile;
m_streams[iId]->iId = iId;
m_streams[iId]->source = STREAM_SOURCE_DEMUX;
m_streams[iId]->pPrivate = pStream;
@@ -1257,6 +1258,20 @@ void CDVDDemuxFFmpeg::GetStreamCodecName(int iStreamId, CStdString &strName)
}
}
+#ifdef FF_PROFILE_DTS_HD_MA
+ /* use profile to determine the DTS type */
+ if (stream->codec == CODEC_ID_DTS)
+ {
+ if (stream->profile == FF_PROFILE_DTS_HD_MA)
+ strName = "dtshd_ma";
+ else if (stream->profile == FF_PROFILE_DTS_HD_HRA)
+ strName = "dtshd_hra";
+ else
+ strName = "dca";
+ return;
+ }
+#endif
+
AVCodec *codec = m_dllAvCodec.avcodec_find_decoder(stream->codec);
if (codec)
strName = codec->name;
diff --git a/xbmc/lib/libjsonrpc/TCPServer.cpp b/xbmc/lib/libjsonrpc/TCPServer.cpp
index 26eaf9f9f7..d62bd3d8c6 100644
--- a/xbmc/lib/libjsonrpc/TCPServer.cpp
+++ b/xbmc/lib/libjsonrpc/TCPServer.cpp
@@ -174,6 +174,7 @@ bool CTCPServer::Initialize()
Deinitialize();
struct sockaddr_in myaddr;
+ memset(&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(m_port);
diff --git a/xbmc/utils/Builtins.cpp b/xbmc/utils/Builtins.cpp
index 71a3a61e24..fbdda6e406 100644
--- a/xbmc/utils/Builtins.cpp
+++ b/xbmc/utils/Builtins.cpp
@@ -644,6 +644,25 @@ int CBuiltins::Execute(const CStdString& execString)
if (g_application.IsPlaying())
g_application.m_pPlayer->Seek(true, false);
}
+ else if (parameter.Left(14).Equals("seekpercentage"))
+ {
+ CStdString offset = "";
+ float offsetpercent;
+ if (parameter.size() == 14)
+ CLog::Log(LOGERROR,"PlayerControl(seekpercentage(n)) called with no argument");
+ else if (parameter.size() < 17) // arg must be at least "(N)"
+ CLog::Log(LOGERROR,"PlayerControl(seekpercentage(n)) called with invalid argument: \"%s\"", parameter.Mid(14).c_str());
+ else
+ {
+ // Don't bother checking the argument: an invalid arg will do seek(0)
+ offset = parameter.Mid(15).TrimRight(")");
+ offsetpercent = (float) atof(offset.c_str());
+ if (offsetpercent < 0 || offsetpercent > 100)
+ CLog::Log(LOGERROR,"PlayerControl(seekpercentage(n)) argument, %f, must be 0-100", offsetpercent);
+ else if (g_application.IsPlaying())
+ g_application.SeekPercentage(offsetpercent);
+ }
+ }
else if( parameter.Equals("showvideomenu") )
{
if( g_application.IsPlaying() && g_application.m_pPlayer )
diff --git a/xbmc/utils/StreamDetails.cpp b/xbmc/utils/StreamDetails.cpp
index 0ee02fb944..7cd5f0ed7a 100644
--- a/xbmc/utils/StreamDetails.cpp
+++ b/xbmc/utils/StreamDetails.cpp
@@ -106,12 +106,15 @@ void CStreamDetailAudio::Serialize(CVariant& value)
int CStreamDetailAudio::GetCodecPriority() const
{
- // technically, truehd, dtsma, and flac are equivalently good (they're all lossless)
+ // technically, truehd, dtshd_ma, and flac are equivalently good (they're all lossless)
+ // however, ffmpeg can't decode dtshd_ma losslessy yet
if (m_strCodec == "flac")
+ return 7;
+ if (m_strCodec == "truehd")
return 6;
- if (m_strCodec == "dtsma")
+ if (m_strCodec == "dtshd_ma")
return 5;
- if (m_strCodec == "truehd")
+ if (m_strCodec == "dtshd_hra")
return 4;
if (m_strCodec == "eac3")
return 3;