summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libhb/bd.c2
-rw-r--r--libhb/common.c45
-rw-r--r--libhb/common.h38
-rw-r--r--libhb/decavcodec.c2
-rw-r--r--libhb/dvd.c42
-rw-r--r--libhb/dvdnav.c42
-rw-r--r--libhb/hb_json.c177
-rw-r--r--libhb/hb_json.h1
-rw-r--r--libhb/preset.c4
-rw-r--r--libhb/scan.c28
-rw-r--r--libhb/stream.c11
-rw-r--r--test/test.c78
12 files changed, 409 insertions, 61 deletions
diff --git a/libhb/bd.c b/libhb/bd.c
index 843fd6c53..23af8934b 100644
--- a/libhb/bd.c
+++ b/libhb/bd.c
@@ -191,7 +191,7 @@ static void add_audio(int track, hb_list_t *list_audio, BLURAY_STREAM_INFO *bdau
lang = lang_for_code2( (char*)bdaudio->lang );
- audio->config.lang.type = 0;
+ audio->config.lang.attributes = HB_AUDIO_ATTR_NONE;
snprintf( audio->config.lang.simple,
sizeof( audio->config.lang.simple ), "%s",
diff --git a/libhb/common.c b/libhb/common.c
index 08bf0f08d..2ffa11b43 100644
--- a/libhb/common.c
+++ b/libhb/common.c
@@ -2040,6 +2040,22 @@ const hb_mixdown_t* hb_mixdown_get_next(const hb_mixdown_t *last)
return ((hb_mixdown_internal_t*)last)->next;
}
+void hb_layout_get_name(char * name, int size, int64_t layout)
+{
+ av_get_channel_layout_string(name, size, 0, layout);
+}
+
+int hb_layout_get_discrete_channel_count(int64_t layout)
+{
+ return av_get_channel_layout_nb_channels(layout);
+}
+
+int hb_layout_get_low_freq_channel_count(int64_t layout)
+{
+ return !!(layout & AV_CH_LOW_FREQUENCY) +
+ !!(layout & AV_CH_LOW_FREQUENCY_2);
+}
+
int hb_video_encoder_get_default(int muxer)
{
if (!(muxer & HB_MUX_MASK))
@@ -2532,6 +2548,31 @@ int hb_autopassthru_get_encoder(int in_codec, int copy_mask, int fallback,
fallback_result;
}
+const char* hb_audio_decoder_get_name(int codec, int codec_param)
+{
+ if (codec & HB_ACODEC_FF_MASK)
+ {
+ AVCodec * codec;
+
+ codec = avcodec_find_decoder(codec_param);
+ if (codec != NULL)
+ {
+ return codec->name;
+ }
+ }
+ else
+ {
+ switch (codec)
+ {
+ case HB_ACODEC_LPCM:
+ return "pcm_dvd";
+ default:
+ break;
+ }
+ }
+ return "unknown";
+}
+
hb_container_t* hb_container_get_from_format(int format)
{
int i;
@@ -5302,9 +5343,9 @@ const char * hb_subsource_name( int source )
case SRTSUB:
return "SRT";
case CC608SUB:
- return "CC";
+ return "CC608";
case CC708SUB:
- return "CC";
+ return "CC708";
case UTF8SUB:
return "UTF-8";
case TX3GSUB:
diff --git a/libhb/common.h b/libhb/common.h
index 20517fc1b..e39c3a778 100644
--- a/libhb/common.h
+++ b/libhb/common.h
@@ -395,6 +395,10 @@ const char* hb_mixdown_get_short_name(int mixdown);
const char* hb_mixdown_sanitize_name(const char *name);
const hb_mixdown_t* hb_mixdown_get_next(const hb_mixdown_t *last);
+void hb_layout_get_name(char * name, int size, int64_t layout);
+int hb_layout_get_discrete_channel_count(int64_t layout);
+int hb_layout_get_low_freq_channel_count(int64_t layout);
+
int hb_video_encoder_get_default(int muxer);
hb_encoder_t* hb_video_encoder_get_from_codec(int codec);
int hb_video_encoder_get_from_name(const char *name);
@@ -421,6 +425,8 @@ const char* hb_audio_encoder_get_long_name(int encoder);
const char* hb_audio_encoder_sanitize_name(const char *name);
const hb_encoder_t* hb_audio_encoder_get_next(const hb_encoder_t *last);
+const char* hb_audio_decoder_get_name(int codec, int codec_param);
+
/*
* Not typically used by the UIs
* (set hb_job_t.acodec_copy_mask, hb_job_t.acodec_fallback instead).
@@ -731,6 +737,14 @@ struct hb_job_s
/* define an invalid VBR quality compatible with all VBR-capable codecs */
#define HB_INVALID_AUDIO_QUALITY (-3.)
+#define HB_AUDIO_ATTR_NONE 0x00
+#define HB_AUDIO_ATTR_NORMAL 0x01
+#define HB_AUDIO_ATTR_VISUALLY_IMPAIRED 0x02
+#define HB_AUDIO_ATTR_COMMENTARY 0x04
+#define HB_AUDIO_ATTR_ALT_COMMENTARY 0x08
+#define HB_AUDIO_ATTR_SECONDARY 0x10
+#define HB_AUDIO_ATTR_DEFAULT 0x20
+
// Update win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_audio_config_s.cs when changing this struct
struct hb_audio_config_s
{
@@ -796,13 +810,7 @@ struct hb_audio_config_s
PRIVATE char description[1024];
PRIVATE char simple[1024];
PRIVATE char iso639_2[4];
-#define HB_AUDIO_TYPE_NONE 0
-#define HB_AUDIO_TYPE_NORMAL 1
-#define HB_AUDIO_TYPE_VISUALLY_IMPAIRED 2
-#define HB_AUDIO_TYPE_COMMENTARY 3
-#define HB_AUDIO_TYPE_ALT_COMMENTARY 4
-#define HB_AUDIO_TYPE_BD_SECONDARY 5
- PRIVATE uint8_t type; /* normal, visually impaired, director's commentary */
+ PRIVATE uint32_t attributes; /* normal, visually impaired, director's commentary */
} lang;
};
@@ -881,6 +889,20 @@ struct hb_chapter_s
*
* Update win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_subtitle_s.cs when changing this struct
*/
+
+#define HB_SUBTITLE_ATTR_UNKNOWN 0x0000
+#define HB_SUBTITLE_ATTR_NORMAL 0x0001
+#define HB_SUBTITLE_ATTR_LARGE 0x0002
+#define HB_SUBTITLE_ATTR_CHILDREN 0x0004
+#define HB_SUBTITLE_ATTR_CC 0x0008
+#define HB_SUBTITLE_ATTR_FORCED 0x0010
+#define HB_SUBTITLE_ATTR_COMMENTARY 0x0020
+#define HB_SUBTITLE_ATTR_4_3 0x0040
+#define HB_SUBTITLE_ATTR_WIDE 0x0080
+#define HB_SUBTITLE_ATTR_LETTERBOX 0x0100
+#define HB_SUBTITLE_ATTR_PANSCAN 0x0200
+#define HB_SUBTITLE_ATTR_DEFAULT 0x0400
+
struct hb_subtitle_s
{
int id;
@@ -893,7 +915,7 @@ struct hb_subtitle_s
enum subsource { VOBSUB, SRTSUB, CC608SUB, /*unused*/CC708SUB, UTF8SUB, TX3GSUB, SSASUB, PGSSUB } source;
char lang[1024];
char iso639_2[4];
- uint8_t type; /* Closed Caption, Childrens, Directors etc */
+ uint32_t attributes; /* Closed Caption, Childrens, Directors etc */
// Color lookup table for VOB subtitle tracks. Each entry is in YCbCr format.
// Must be filled out by the demuxer for VOB subtitle tracks.
diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c
index 460410731..d308a49d5 100644
--- a/libhb/decavcodec.c
+++ b/libhb/decavcodec.c
@@ -1237,7 +1237,7 @@ static int decodeFrame( hb_work_object_t *w, packet_info_t * packet_info )
subtitle->source = CC608SUB;
subtitle->config.dest = PASSTHRUSUB;
subtitle->codec = WORK_DECCC608;
- subtitle->type = 5;
+ subtitle->attributes = HB_SUBTITLE_ATTR_CC;
/*
* The language of the subtitles will be the same as the
diff --git a/libhb/dvd.c b/libhb/dvd.c
index 078806d89..4dfd81661 100644
--- a/libhb/dvd.c
+++ b/libhb/dvd.c
@@ -205,55 +205,72 @@ static void add_subtitle( hb_list_t * list_subtitle, int position,
subtitle->substream_type = 0x20 + position;
subtitle->codec = WORK_DECVOBSUB;
- subtitle->type = lang_extension;
-
memcpy(subtitle->palette, palette, 16 * sizeof(uint32_t));
subtitle->palette_set = 1;
switch (lang_extension)
{
+ case 1:
+ subtitle->attributes = HB_SUBTITLE_ATTR_NORMAL;
+ break;
case 2:
+ subtitle->attributes = HB_SUBTITLE_ATTR_LARGE;
strcat(subtitle->lang, " Large Type");
break;
case 3:
+ subtitle->attributes = HB_SUBTITLE_ATTR_CHILDREN;
strcat(subtitle->lang, " Children");
break;
case 5:
+ subtitle->attributes = HB_SUBTITLE_ATTR_CC;
strcat(subtitle->lang, " Closed Caption");
break;
case 6:
+ subtitle->attributes = HB_SUBTITLE_ATTR_CC | HB_SUBTITLE_ATTR_LARGE;
strcat(subtitle->lang, " Closed Caption, Large Type");
break;
case 7:
+ subtitle->attributes = HB_SUBTITLE_ATTR_CC |
+ HB_SUBTITLE_ATTR_CHILDREN;
strcat(subtitle->lang, " Closed Caption, Children");
break;
case 9:
+ subtitle->attributes = HB_SUBTITLE_ATTR_FORCED;
strcat(subtitle->lang, " Forced");
break;
case 13:
+ subtitle->attributes = HB_SUBTITLE_ATTR_COMMENTARY;
strcat(subtitle->lang, " Director's Commentary");
break;
case 14:
+ subtitle->attributes = HB_SUBTITLE_ATTR_COMMENTARY |
+ HB_SUBTITLE_ATTR_LARGE;
strcat(subtitle->lang, " Director's Commentary, Large Type");
break;
case 15:
+ subtitle->attributes = HB_SUBTITLE_ATTR_COMMENTARY |
+ HB_SUBTITLE_ATTR_CHILDREN;
strcat(subtitle->lang, " Director's Commentary, Children");
default:
+ subtitle->attributes = HB_SUBTITLE_ATTR_UNKNOWN;
break;
}
-
switch (style)
{
case HB_VOBSUB_STYLE_4_3:
+ subtitle->attributes |= HB_SUBTITLE_ATTR_4_3;
strcat(subtitle->lang, " (4:3)");
break;
case HB_VOBSUB_STYLE_WIDE:
+ subtitle->attributes |= HB_SUBTITLE_ATTR_WIDE;
strcat(subtitle->lang, " (Wide Screen)");
break;
case HB_VOBSUB_STYLE_LETTERBOX:
+ subtitle->attributes |= HB_SUBTITLE_ATTR_LETTERBOX;
strcat(subtitle->lang, " (Letterbox)");
break;
case HB_VOBSUB_STYLE_PANSCAN:
+ subtitle->attributes |= HB_SUBTITLE_ATTR_PANSCAN;
strcat(subtitle->lang, " (Pan & Scan)");
break;
}
@@ -526,7 +543,24 @@ static hb_title_t * hb_dvdread_title_scan( hb_dvd_t * e, int t, uint64_t min_dur
lang = lang_for_code( lang_code );
- audio->config.lang.type = lang_extension;
+ switch ( lang_extension )
+ {
+ case 1:
+ audio->config.lang.attributes = HB_AUDIO_ATTR_NORMAL;
+ break;
+ case 2:
+ audio->config.lang.attributes = HB_AUDIO_ATTR_VISUALLY_IMPAIRED;
+ break;
+ case 3:
+ audio->config.lang.attributes = HB_AUDIO_ATTR_COMMENTARY;
+ break;
+ case 4:
+ audio->config.lang.attributes = HB_AUDIO_ATTR_ALT_COMMENTARY;
+ break;
+ default:
+ audio->config.lang.attributes = HB_AUDIO_ATTR_NONE;
+ break;
+ }
snprintf( audio->config.lang.simple,
sizeof( audio->config.lang.simple ), "%s",
diff --git a/libhb/dvdnav.c b/libhb/dvdnav.c
index 4a1cbfb57..acc30007b 100644
--- a/libhb/dvdnav.c
+++ b/libhb/dvdnav.c
@@ -349,55 +349,72 @@ static void add_subtitle( hb_list_t * list_subtitle, int position,
subtitle->substream_type = 0x20 + position;
subtitle->codec = WORK_DECVOBSUB;
- subtitle->type = lang_extension;
-
memcpy(subtitle->palette, palette, 16 * sizeof(uint32_t));
subtitle->palette_set = 1;
switch (lang_extension)
{
+ case 1:
+ subtitle->attributes = HB_SUBTITLE_ATTR_NORMAL;
+ break;
case 2:
+ subtitle->attributes = HB_SUBTITLE_ATTR_LARGE;
strcat(subtitle->lang, " Large Type");
break;
case 3:
+ subtitle->attributes = HB_SUBTITLE_ATTR_CHILDREN;
strcat(subtitle->lang, " Children");
break;
case 5:
+ subtitle->attributes = HB_SUBTITLE_ATTR_CC;
strcat(subtitle->lang, " Closed Caption");
break;
case 6:
+ subtitle->attributes = HB_SUBTITLE_ATTR_CC | HB_SUBTITLE_ATTR_LARGE;
strcat(subtitle->lang, " Closed Caption, Large Type");
break;
case 7:
+ subtitle->attributes = HB_SUBTITLE_ATTR_CC |
+ HB_SUBTITLE_ATTR_CHILDREN;
strcat(subtitle->lang, " Closed Caption, Children");
break;
case 9:
+ subtitle->attributes = HB_SUBTITLE_ATTR_FORCED;
strcat(subtitle->lang, " Forced");
break;
case 13:
+ subtitle->attributes = HB_SUBTITLE_ATTR_COMMENTARY;
strcat(subtitle->lang, " Director's Commentary");
break;
case 14:
+ subtitle->attributes = HB_SUBTITLE_ATTR_COMMENTARY |
+ HB_SUBTITLE_ATTR_LARGE;
strcat(subtitle->lang, " Director's Commentary, Large Type");
break;
case 15:
+ subtitle->attributes = HB_SUBTITLE_ATTR_COMMENTARY |
+ HB_SUBTITLE_ATTR_CHILDREN;
strcat(subtitle->lang, " Director's Commentary, Children");
default:
+ subtitle->attributes = HB_SUBTITLE_ATTR_UNKNOWN;
break;
}
-
switch (style)
{
case HB_VOBSUB_STYLE_4_3:
+ subtitle->attributes |= HB_SUBTITLE_ATTR_4_3;
strcat(subtitle->lang, " (4:3)");
break;
case HB_VOBSUB_STYLE_WIDE:
+ subtitle->attributes |= HB_SUBTITLE_ATTR_WIDE;
strcat(subtitle->lang, " (Wide Screen)");
break;
case HB_VOBSUB_STYLE_LETTERBOX:
+ subtitle->attributes |= HB_SUBTITLE_ATTR_LETTERBOX;
strcat(subtitle->lang, " (Letterbox)");
break;
case HB_VOBSUB_STYLE_PANSCAN:
+ subtitle->attributes |= HB_SUBTITLE_ATTR_PANSCAN;
strcat(subtitle->lang, " (Pan & Scan)");
break;
}
@@ -685,6 +702,24 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t, uint64_t min_dura
{
continue;
}
+ switch ( lang_extension )
+ {
+ case 1:
+ audio->config.lang.attributes = HB_AUDIO_ATTR_NORMAL;
+ break;
+ case 2:
+ audio->config.lang.attributes = HB_AUDIO_ATTR_VISUALLY_IMPAIRED;
+ break;
+ case 3:
+ audio->config.lang.attributes = HB_AUDIO_ATTR_COMMENTARY;
+ break;
+ case 4:
+ audio->config.lang.attributes = HB_AUDIO_ATTR_ALT_COMMENTARY;
+ break;
+ default:
+ audio->config.lang.attributes = HB_AUDIO_ATTR_NONE;
+ break;
+ }
/* Check for duplicate tracks */
audio_tmp = NULL;
@@ -706,7 +741,6 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t, uint64_t min_dura
lang = lang_for_code( lang_code );
- audio->config.lang.type = lang_extension;
snprintf( audio->config.lang.simple,
sizeof( audio->config.lang.simple ), "%s",
diff --git a/libhb/hb_json.c b/libhb/hb_json.c
index 5a3b4ca9d..615458b31 100644
--- a/libhb/hb_json.c
+++ b/libhb/hb_json.c
@@ -19,20 +19,52 @@
*/
hb_dict_t* hb_state_to_dict( hb_state_t * state)
{
+ const char * state_s;
hb_dict_t *dict = NULL;
json_error_t error;
switch (state->state)
{
case HB_STATE_IDLE:
+ state_s = "IDLE";
+ break;
+ case HB_STATE_SCANNING:
+ state_s = "SCANNING";
+ break;
+ case HB_STATE_SCANDONE:
+ state_s = "SCANDONE";
+ break;
+ case HB_STATE_WORKING:
+ state_s = "WORKING";
+ break;
+ case HB_STATE_PAUSED:
+ state_s = "PAUSED";
+ break;
+ case HB_STATE_SEARCHING:
+ state_s = "SEARCHING";
+ break;
+ case HB_STATE_WORKDONE:
+ state_s = "WORKDONE";
+ break;
+ case HB_STATE_MUXING:
+ state_s = "MUXING";
+ break;
+ default:
+ state_s = "UNKNOWN";
+ break;
+ }
+
+ switch (state->state)
+ {
+ case HB_STATE_IDLE:
dict = json_pack_ex(&error, 0, "{s:o}",
- "State", hb_value_int(state->state));
+ "State", hb_value_string(state_s));
break;
case HB_STATE_SCANNING:
case HB_STATE_SCANDONE:
dict = json_pack_ex(&error, 0,
"{s:o, s{s:o, s:o, s:o, s:o, s:o}}",
- "State", hb_value_int(state->state),
+ "State", hb_value_string(state_s),
"Scanning",
"Progress", hb_value_double(state->param.scanning.progress),
"Preview", hb_value_int(state->param.scanning.preview_cur),
@@ -45,7 +77,7 @@ hb_dict_t* hb_state_to_dict( hb_state_t * state)
case HB_STATE_SEARCHING:
dict = json_pack_ex(&error, 0,
"{s:o, s{s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o}}",
- "State", hb_value_int(state->state),
+ "State", hb_value_string(state_s),
"Working",
"Progress", hb_value_double(state->param.working.progress),
"PassID", hb_value_int(state->param.working.pass_id),
@@ -61,19 +93,21 @@ hb_dict_t* hb_state_to_dict( hb_state_t * state)
case HB_STATE_WORKDONE:
dict = json_pack_ex(&error, 0,
"{s:o, s{s:o}}",
- "State", hb_value_int(state->state),
+ "State", hb_value_string(state_s),
"WorkDone",
"Error", hb_value_int(state->param.workdone.error));
break;
case HB_STATE_MUXING:
dict = json_pack_ex(&error, 0,
"{s:o, s{s:o}}",
- "State", hb_value_int(state->state),
+ "State", hb_value_string(state_s),
"Muxing",
"Progress", hb_value_double(state->param.muxing.progress));
break;
default:
- hb_error("hb_state_to_json: unrecognized state %d", state->state);
+ dict = json_pack_ex(&error, 0, "{s:o}",
+ "State", hb_value_string(state_s));
+ hb_error("hb_state_to_dict: unrecognized state %d", state->state);
break;
}
if (dict == NULL)
@@ -83,6 +117,34 @@ hb_dict_t* hb_state_to_dict( hb_state_t * state)
return dict;
}
+hb_dict_t * hb_version_dict()
+{
+ hb_dict_t * dict;
+ json_error_t error;
+
+ dict = json_pack_ex(&error, 0,
+ "{s:o, s:o, s:o, s{s:o, s:o, s:o}, s:o, s:o, s:o, s:o, s:o}",
+ "Name", hb_value_string(HB_PROJECT_NAME),
+ "Official", hb_value_bool(HB_PROJECT_REPO_OFFICIAL),
+ "Type", hb_value_string(HB_PROJECT_REPO_TYPE),
+ "Version",
+ "Major", hb_value_int(HB_PROJECT_VERSION_MAJOR),
+ "Minor", hb_value_int(HB_PROJECT_VERSION_MINOR),
+ "Point", hb_value_int(HB_PROJECT_VERSION_POINT),
+ "VersionString", hb_value_string(HB_PROJECT_VERSION),
+ "RepoHash", hb_value_string(HB_PROJECT_REPO_HASH),
+ "RepoDate", hb_value_string(HB_PROJECT_REPO_DATE),
+ "System", hb_value_string(HB_PROJECT_BUILD_SYSTEMF),
+ "Arch", hb_value_string(HB_PROJECT_BUILD_ARCH));
+ if (dict == NULL)
+ {
+ hb_error("json pack failure: %s", error.text);
+ return NULL;
+ }
+
+ return dict;
+}
+
/**
* Get the current state of an hb instance as a json string
* @param h - Pointer to an hb_handle_t hb instance
@@ -100,6 +162,55 @@ char* hb_get_state_json( hb_handle_t * h )
return json_state;
}
+hb_dict_t * hb_audio_attributes_to_dict(uint32_t attributes)
+{
+ json_error_t error;
+ hb_dict_t * dict;
+
+ dict = json_pack_ex(&error, 0,
+ "{s:o, s:o, s:o, s:o, s:o, s:o}",
+ "Normal", hb_value_bool(attributes & HB_AUDIO_ATTR_NORMAL),
+ "VisuallyImpaired", hb_value_bool(attributes &
+ HB_AUDIO_ATTR_VISUALLY_IMPAIRED),
+ "Commentary", hb_value_bool(attributes &
+ HB_AUDIO_ATTR_COMMENTARY),
+ "AltCommentary", hb_value_bool(attributes &
+ HB_AUDIO_ATTR_ALT_COMMENTARY),
+ "Secondary", hb_value_bool(attributes & HB_AUDIO_ATTR_SECONDARY),
+ "Default", hb_value_bool(attributes & HB_AUDIO_ATTR_DEFAULT));
+ if (dict == NULL)
+ {
+ hb_error("json pack failure: %s", error.text);
+ }
+ return dict;
+}
+
+hb_dict_t * hb_subtitle_attributes_to_dict(uint32_t attributes)
+{
+ json_error_t error;
+ hb_dict_t * dict;
+
+ dict = json_pack_ex(&error, 0,
+ "{s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o}",
+ "Normal", hb_value_bool(attributes & HB_SUBTITLE_ATTR_NORMAL),
+ "Large", hb_value_bool(attributes & HB_SUBTITLE_ATTR_LARGE),
+ "Children", hb_value_bool(attributes & HB_SUBTITLE_ATTR_CHILDREN),
+ "ClosedCaption", hb_value_bool(attributes & HB_SUBTITLE_ATTR_CC),
+ "Forced", hb_value_bool(attributes & HB_SUBTITLE_ATTR_FORCED),
+ "Commentary", hb_value_bool(attributes &
+ HB_SUBTITLE_ATTR_COMMENTARY),
+ "4By3", hb_value_bool(attributes & HB_SUBTITLE_ATTR_4_3),
+ "Wide", hb_value_bool(attributes & HB_SUBTITLE_ATTR_WIDE),
+ "Letterbox", hb_value_bool(attributes & HB_SUBTITLE_ATTR_LETTERBOX),
+ "PanScan", hb_value_bool(attributes & HB_SUBTITLE_ATTR_PANSCAN),
+ "Default", hb_value_bool(attributes & HB_SUBTITLE_ATTR_DEFAULT));
+ if (dict == NULL)
+ {
+ hb_error("json pack failure: %s", error.text);
+ }
+ return dict;
+}
+
static hb_dict_t* hb_title_to_dict_internal( hb_title_t *title )
{
hb_dict_t *dict;
@@ -255,18 +366,37 @@ static hb_dict_t* hb_title_to_dict_internal( hb_title_t *title )
hb_dict_t * audio_list = hb_value_array_init();
for (ii = 0; ii < hb_list_count(title->list_audio); ii++)
{
- hb_dict_t *audio_dict;
- hb_audio_t *audio = hb_list_item(title->list_audio, ii);
+ const char * codec_name;
+ char channel_layout_name[64];
+ int channel_count, lfe_count;
+ hb_dict_t * audio_dict, * attributes;
+ hb_audio_t * audio = hb_list_item(title->list_audio, ii);
+ codec_name = hb_audio_decoder_get_name(audio->config.in.codec,
+ audio->config.in.codec_param);
+ hb_layout_get_name(channel_layout_name, sizeof(channel_layout_name),
+ audio->config.in.channel_layout);
+ channel_count = hb_layout_get_discrete_channel_count(
+ audio->config.in.channel_layout);
+ lfe_count = hb_layout_get_low_freq_channel_count(
+ audio->config.in.channel_layout);
+
+
+ attributes = hb_audio_attributes_to_dict(audio->config.lang.attributes);
audio_dict = json_pack_ex(&error, 0,
- "{s:o, s:o, s:o, s:o, s:o, s:o, s:o}",
- "Description", hb_value_string(audio->config.lang.description),
- "Language", hb_value_string(audio->config.lang.simple),
- "LanguageCode", hb_value_string(audio->config.lang.iso639_2),
- "Codec", hb_value_int(audio->config.in.codec),
- "SampleRate", hb_value_int(audio->config.in.samplerate),
- "BitRate", hb_value_int(audio->config.in.bitrate),
- "ChannelLayout", hb_value_int(audio->config.in.channel_layout));
+ "{s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o}",
+ "Description", hb_value_string(audio->config.lang.description),
+ "Language", hb_value_string(audio->config.lang.simple),
+ "LanguageCode", hb_value_string(audio->config.lang.iso639_2),
+ "Attributes", attributes,
+ "Codec", hb_value_int(audio->config.in.codec),
+ "CodecName", hb_value_string(codec_name),
+ "SampleRate", hb_value_int(audio->config.in.samplerate),
+ "BitRate", hb_value_int(audio->config.in.bitrate),
+ "ChannelLayout", hb_value_int(audio->config.in.channel_layout),
+ "ChannelLayoutName", hb_value_string(channel_layout_name),
+ "ChannelCount", hb_value_int(channel_count),
+ "LFECount", hb_value_int(lfe_count));
if (audio_dict == NULL)
{
hb_error("json pack failure: %s", error.text);
@@ -277,16 +407,21 @@ static hb_dict_t* hb_title_to_dict_internal( hb_title_t *title )
hb_dict_set(dict, "AudioList", audio_list);
// process subtitle list
- hb_dict_t * subtitle_list = hb_value_array_init();
+ hb_value_array_t * subtitle_list = hb_value_array_init();
for (ii = 0; ii < hb_list_count(title->list_subtitle); ii++)
{
- hb_dict_t *subtitle_dict;
- hb_subtitle_t *subtitle = hb_list_item(title->list_subtitle, ii);
+ const char * format;
+ hb_dict_t * subtitle_dict, * attributes;
+ hb_subtitle_t * subtitle = hb_list_item(title->list_subtitle, ii);
+ format = subtitle->format == PICTURESUB ? "bitmap" : "text";
+ attributes = hb_subtitle_attributes_to_dict(subtitle->attributes);
subtitle_dict = json_pack_ex(&error, 0,
- "{s:o, s:o, s:o, s:o}",
- "Format", hb_value_int(subtitle->format),
+ "{s:o, s:o, s:o, s:o, s:o, s:o}",
+ "Format", hb_value_string(format),
"Source", hb_value_int(subtitle->source),
+ "SourceName", hb_value_string(hb_subsource_name(subtitle->source)),
+ "Attributes", attributes,
"Language", hb_value_string(subtitle->lang),
"LanguageCode", hb_value_string(subtitle->iso639_2));
if (subtitle_dict == NULL)
diff --git a/libhb/hb_json.h b/libhb/hb_json.h
index 26afd4408..54ac92a46 100644
--- a/libhb/hb_json.h
+++ b/libhb/hb_json.h
@@ -35,6 +35,7 @@ char * hb_get_preview_params_json(int title_idx, int preview_idx,
int deinterlace, hb_geometry_settings_t *settings);
char * hb_get_preview_json(hb_handle_t * h, const char *json_param);
void hb_json_job_scan( hb_handle_t * h, const char * json_job );
+hb_dict_t * hb_version_dict(void);
#ifdef __cplusplus
}
diff --git a/libhb/preset.c b/libhb/preset.c
index 4f8a62534..4693fca2a 100644
--- a/libhb/preset.c
+++ b/libhb/preset.c
@@ -404,8 +404,8 @@ static int find_audio_track(const hb_title_t *title,
// When behavior is "all" matching tracks,
// allow any audio track type
if ((behavior == 2 ||
- audio->lang.type == HB_AUDIO_TYPE_NONE ||
- audio->lang.type == HB_AUDIO_TYPE_NORMAL) &&
+ audio->lang.attributes == HB_AUDIO_ATTR_NONE ||
+ audio->lang.attributes == HB_AUDIO_ATTR_NORMAL) &&
(!strcmp(lang, audio->lang.iso639_2) || !strcmp(lang, "und")))
{
return ii;
diff --git a/libhb/scan.c b/libhb/scan.c
index b096c4e4c..56ca56c90 100644
--- a/libhb/scan.c
+++ b/libhb/scan.c
@@ -1293,19 +1293,23 @@ static void LookForAudio(hb_scan_t *scan, hb_title_t * title, hb_buffer_t * b)
sprintf(audio->config.lang.description, "%s (%s)",
audio->config.lang.simple, codec_name);
- switch (audio->config.lang.type)
+ if (audio->config.lang.attributes & HB_AUDIO_ATTR_VISUALLY_IMPAIRED)
{
- case 2:
- strcat(audio->config.lang.description, " (Visually Impaired)");
- break;
- case 3:
- strcat(audio->config.lang.description, " (Director's Commentary 1)");
- break;
- case 4:
- strcat(audio->config.lang.description, " (Director's Commentary 2)");
- break;
- default:
- break;
+ strncat(audio->config.lang.description, " (Visually Impaired)",
+ sizeof(audio->config.lang.description) -
+ strlen(audio->config.lang.description) - 1);
+ }
+ if (audio->config.lang.attributes & HB_AUDIO_ATTR_COMMENTARY)
+ {
+ strncat(audio->config.lang.description, " (Director's Commentary 1)",
+ sizeof(audio->config.lang.description) -
+ strlen(audio->config.lang.description) - 1);
+ }
+ if (audio->config.lang.attributes & HB_AUDIO_ATTR_ALT_COMMENTARY)
+ {
+ strncat(audio->config.lang.description, " (Director's Commentary 2)",
+ sizeof(audio->config.lang.description) -
+ strlen(audio->config.lang.description) - 1);
}
if (audio->config.in.channel_layout)
diff --git a/libhb/stream.c b/libhb/stream.c
index 6d849d776..a2d50447e 100644
--- a/libhb/stream.c
+++ b/libhb/stream.c
@@ -1930,7 +1930,6 @@ static void set_audio_description(hb_audio_t *audio, iso639_lang_t *lang)
strlen( lang->native_name ) ? lang->native_name : lang->eng_name );
snprintf( audio->config.lang.iso639_2,
sizeof( audio->config.lang.iso639_2 ), "%s", lang->iso639_2 );
- audio->config.lang.type = 0;
}
// Sort specifies the index in the audio list where you would
@@ -5152,6 +5151,11 @@ static void add_ffmpeg_audio(hb_title_t *title, hb_stream_t *stream, int id)
break;
}
+ if (st->disposition & AV_DISPOSITION_DEFAULT)
+ {
+ audio->config.lang.attributes |= HB_AUDIO_ATTR_DEFAULT;
+ }
+
set_audio_description(audio,
lang_for_code2(tag != NULL ? tag->value : "und"));
hb_list_add(title->list_audio, audio);
@@ -5358,6 +5362,11 @@ static void add_ffmpeg_subtitle( hb_title_t *title, hb_stream_t *stream, int id
if (st->disposition & AV_DISPOSITION_DEFAULT)
{
subtitle->config.default_track = 1;
+ subtitle->attributes |= HB_SUBTITLE_ATTR_DEFAULT;
+ }
+ if (st->disposition & AV_DISPOSITION_FORCED)
+ {
+ subtitle->attributes |= HB_SUBTITLE_ATTR_FORCED;
}
subtitle->track = hb_list_count(title->list_subtitle);
diff --git a/test/test.c b/test/test.c
index 1e3238989..da1f07c2e 100644
--- a/test/test.c
+++ b/test/test.c
@@ -58,6 +58,7 @@
/* Options */
static int debug = HB_DEBUG_ALL;
+static int json = 0;
static int align_av_start = -1;
static int dvdnav = 1;
static char * input = NULL;
@@ -717,13 +718,27 @@ static void PrintTitleInfo( hb_title_t * title, int feature )
static void PrintTitleSetInfo( hb_title_set_t * title_set )
{
- int i;
- hb_title_t * title;
+ if (json)
+ {
+ hb_dict_t * title_set_dict;
+ char * title_set_json;
- for( i = 0; i < hb_list_count( title_set->list_title ); i++ )
+ title_set_dict = hb_title_set_to_dict(title_set);
+ title_set_json = hb_value_get_json(title_set_dict);
+ hb_value_free(&title_set_dict);
+ fprintf(stdout, "JSON Title Set: %s\n", title_set_json);
+ free(title_set_json);
+ }
+ else
{
- title = hb_list_item( title_set->list_title, i );
- PrintTitleInfo( title, title_set->feature );
+ int i;
+ hb_title_t * title;
+
+ for( i = 0; i < hb_list_count( title_set->list_title ); i++ )
+ {
+ title = hb_list_item( title_set->list_title, i );
+ PrintTitleInfo( title, title_set->feature );
+ }
}
}
@@ -806,6 +821,19 @@ static void lang_list_remove(hb_value_array_t *list, const char *lang)
}
}
+static void show_progress_json(hb_state_t * state)
+{
+ hb_dict_t * state_dict;
+ char * state_json;
+
+ state_dict = hb_state_to_dict(state);
+ state_json = hb_value_get_json(state_dict);
+ hb_value_free(&state_dict);
+ fprintf(stdout, "Progress: %s\n", state_json);
+ free(state_json);
+ fflush(stderr);
+}
+
static int HandleEvents(hb_handle_t * h, hb_dict_t *preset_dict)
{
hb_state_t s;
@@ -820,6 +848,11 @@ static int HandleEvents(hb_handle_t * h, hb_dict_t *preset_dict)
#define p s.param.scanning
case HB_STATE_SCANNING:
/* Show what title is currently being scanned */
+ if (json)
+ {
+ show_progress_json(&s);
+ break;
+ }
if (p.preview_cur)
{
fprintf(stderr, "%sScanning title %d of %d, preview %d, %.2f %%",
@@ -941,6 +974,11 @@ static int HandleEvents(hb_handle_t * h, hb_dict_t *preset_dict)
#define p s.param.working
case HB_STATE_SEARCHING:
+ if (json)
+ {
+ show_progress_json(&s);
+ break;
+ }
fprintf( stdout, "%sEncoding: task %d of %d, Searching for start time, %.2f %%",
stdout_sep, p.pass, p.pass_count, 100.0 * p.progress );
if( p.seconds > -1 )
@@ -952,6 +990,11 @@ static int HandleEvents(hb_handle_t * h, hb_dict_t *preset_dict)
break;
case HB_STATE_WORKING:
+ if (json)
+ {
+ show_progress_json(&s);
+ break;
+ }
fprintf( stdout, "%sEncoding: task %d of %d, %.2f %%",
stdout_sep, p.pass, p.pass_count, 100.0 * p.progress );
if( p.seconds > -1 )
@@ -967,6 +1010,11 @@ static int HandleEvents(hb_handle_t * h, hb_dict_t *preset_dict)
#define p s.param.muxing
case HB_STATE_MUXING:
{
+ if (json)
+ {
+ show_progress_json(&s);
+ break;
+ }
if (show_mux_warning)
{
fprintf( stdout, "%sMuxing: this may take awhile...", stdout_sep );
@@ -980,6 +1028,10 @@ static int HandleEvents(hb_handle_t * h, hb_dict_t *preset_dict)
#define p s.param.workdone
case HB_STATE_WORKDONE:
/* Print error if any, then exit */
+ if (json)
+ {
+ show_progress_json(&s);
+ }
switch( p.error )
{
case HB_ERROR_NONE:
@@ -1227,6 +1279,8 @@ static void ShowHelp()
"\n"
" -h, --help Print help\n"
" --version Print version\n"
+" --json Log title, progress, and version info in\n"
+" JSON format\n"
" -v, --verbose[=number] Be verbose (optional argument: logging level)\n"
" -Z. --preset <string> Select preset by name (case-sensitive)\n"
" Enclose names containing spaces in double quotation\n"
@@ -2040,6 +2094,7 @@ static int ParseOptions( int argc, char ** argv )
#define FILTER_UNSHARP_TUNE 313
#define FILTER_LAPSHARP 314
#define FILTER_LAPSHARP_TUNE 315
+ #define JSON_LOGGING 316
for( ;; )
{
@@ -2202,6 +2257,7 @@ static int ParseOptions( int argc, char ** argv )
{ "pfr", no_argument, &cfr, 2 },
{ "audio-copy-mask", required_argument, NULL, ALLOWED_AUDIO_COPY },
{ "audio-fallback", required_argument, NULL, AUDIO_FALLBACK },
+ { "json", no_argument, NULL, JSON_LOGGING },
{ 0, 0, 0, 0 }
};
@@ -2233,6 +2289,18 @@ static int ParseOptions( int argc, char ** argv )
case DESCRIBE:
printf("%s\n", hb_get_full_description());
return 1;
+ case JSON_LOGGING:
+ {
+ hb_dict_t * version_dict;
+ char * version_json;
+
+ version_dict = hb_version_dict();
+ version_json = hb_value_get_json(version_dict);
+ hb_value_free(&version_dict);
+ fprintf(stdout, "Version: %s\n", version_json);
+ free(version_json);
+ json = 1;
+ } break;
case 'v':
if( optarg != NULL )
{