]> granicus.if.org Git - handbrake/commitdiff
CLI: add option to log version, title, and progress in json
authorJohn Stebbins <jstebbins.hb@gmail.com>
Mon, 6 Nov 2017 18:48:26 +0000 (10:48 -0800)
committerGitHub <noreply@github.com>
Mon, 6 Nov 2017 18:48:26 +0000 (10:48 -0800)
This is useful for scripts and other frontends that need to parse CLI output.

12 files changed:
libhb/bd.c
libhb/common.c
libhb/common.h
libhb/decavcodec.c
libhb/dvd.c
libhb/dvdnav.c
libhb/hb_json.c
libhb/hb_json.h
libhb/preset.c
libhb/scan.c
libhb/stream.c
test/test.c

index 843fd6c5350fdcf056a84c6c46849d2c3c5b0611..23af8934b3271cf18efc9a4c962b41e72bdb1bb0 100644 (file)
@@ -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",
index 08bf0f08dcd3c555bda4815a5df8e3f360c93430..2ffa11b433f017a30c786ff56e88f8e84699b16c 100644 (file)
@@ -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:
index 20517fc1ba5d97cda98d6c769c1190b9f0c7b1b4..e39c3a7783e201ad44a4fda4135fffab606e163f 100644 (file)
@@ -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.
index 4604107317c25ccf2cb5797620e06277eba9d09e..d308a49d5f508e1fc5c72be4b19f97efca49b0c9 100644 (file)
@@ -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
index 078806d89b14794286c6e85f29ee259b224b6166..4dfd81661314b61bdba03b652ea73498d0096a9e 100644 (file)
@@ -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",
index 4a1cbfb5775899130200024ef500c8ff03cb343c..acc30007bd1cc8b95fbff10eda933ecc8b2a9e40 100644 (file)
@@ -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",
index 5a3b4ca9d77fa849ef2bc86947a577ed04688d5b..615458b31eeb7d6f5506633203776d9e9f69e7a8 100644 (file)
  */
 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)
index 26afd4408f4baf87ea2060f83202494b19332b64..54ac92a46d5b615134908b055e80d77e8b3620f9 100644 (file)
@@ -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
 }
index 4f8a62534bb2e2d746618e6ebb35f15413d9a0eb..4693fca2a05f84e8a22f356053eead482558de79 100644 (file)
@@ -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;
index b096c4e4c95e185114a7ab7040a99a7dbf04eec7..56ca56c90b5e94051ec00448a37370b5282a955e 100644 (file)
@@ -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)
index 6d849d776756abbbc7c2c567cc469aec96176341..a2d50447ec426d670cef26fe7d4ff60e6e759b75 100644 (file)
@@ -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);
index 1e3238989a3df2bc4103f3a92d75114126892816..da1f07c2e6c5861bacd5ed27f2b83bd4cf0db6dc 100644 (file)
@@ -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 )
                 {