diff options
-rw-r--r-- | libhb/bd.c | 2 | ||||
-rw-r--r-- | libhb/common.c | 45 | ||||
-rw-r--r-- | libhb/common.h | 38 | ||||
-rw-r--r-- | libhb/decavcodec.c | 2 | ||||
-rw-r--r-- | libhb/dvd.c | 42 | ||||
-rw-r--r-- | libhb/dvdnav.c | 42 | ||||
-rw-r--r-- | libhb/hb_json.c | 177 | ||||
-rw-r--r-- | libhb/hb_json.h | 1 | ||||
-rw-r--r-- | libhb/preset.c | 4 | ||||
-rw-r--r-- | libhb/scan.c | 28 | ||||
-rw-r--r-- | libhb/stream.c | 11 | ||||
-rw-r--r-- | test/test.c | 78 |
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 ) { |