diff options
author | Lars Op den Kamp <lars@opdenkamp.eu> | 2011-01-23 03:26:52 +0100 |
---|---|---|
committer | Lars Op den Kamp <lars@opdenkamp.eu> | 2011-01-23 03:26:52 +0100 |
commit | 4e98a514c6a2975ec234fe19fe058e7e74bcfb7d (patch) | |
tree | 678a498293daf821732088ef837c6525363cdc2d | |
parent | b7ed68894bbdb0c92d9547a54644dc252ac70dd5 (diff) | |
parent | 8d73cbde1dcd240d80bee9301d0321703a15c995 (diff) |
Merge remote branch 'upstream/master'
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 Binary files differnew file mode 100644 index 0000000000..7a60c9fea6 --- /dev/null +++ b/addons/skin.confluence/media/flagging/audio/dtshd_hra.png diff --git a/addons/skin.confluence/media/flagging/audio/dtshd_ma.png b/addons/skin.confluence/media/flagging/audio/dtshd_ma.png Binary files differnew file mode 100644 index 0000000000..71e743ec38 --- /dev/null +++ b/addons/skin.confluence/media/flagging/audio/dtshd_ma.png diff --git a/system/players/dvdplayer/avcodec-52.dll b/system/players/dvdplayer/avcodec-52.dll Binary files differindex ae847eeb0a..5b5d531298 100644 --- a/system/players/dvdplayer/avcodec-52.dll +++ b/system/players/dvdplayer/avcodec-52.dll diff --git a/system/players/dvdplayer/avformat-52.dll b/system/players/dvdplayer/avformat-52.dll Binary files differindex 83247ac686..f0b2e7a878 100644 --- a/system/players/dvdplayer/avformat-52.dll +++ b/system/players/dvdplayer/avformat-52.dll diff --git a/system/players/dvdplayer/avutil-50.dll b/system/players/dvdplayer/avutil-50.dll Binary files differindex 45c439a001..d098b67dab 100644 --- a/system/players/dvdplayer/avutil-50.dll +++ b/system/players/dvdplayer/avutil-50.dll diff --git a/system/players/dvdplayer/postproc-51.dll b/system/players/dvdplayer/postproc-51.dll Binary files differindex 03c227532e..a9713d17e7 100644 --- a/system/players/dvdplayer/postproc-51.dll +++ b/system/players/dvdplayer/postproc-51.dll diff --git a/system/players/dvdplayer/swscale-0.6.1.dll b/system/players/dvdplayer/swscale-0.6.1.dll Binary files differindex 5efdb3e5b3..f6cdd001b2 100644 --- a/system/players/dvdplayer/swscale-0.6.1.dll +++ b/system/players/dvdplayer/swscale-0.6.1.dll 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; |