diff options
-rw-r--r-- | gtk/src/hb-backend.c | 35 | ||||
-rw-r--r-- | libhb/colormap.c | 721 | ||||
-rw-r--r-- | libhb/colormap.h | 20 | ||||
-rw-r--r-- | libhb/common.c | 5 | ||||
-rw-r--r-- | libhb/deccc608sub.c | 745 | ||||
-rw-r--r-- | libhb/deccc608sub.h | 3 | ||||
-rw-r--r-- | libhb/rendersub.c | 317 | ||||
-rw-r--r-- | libhb/stream.c | 9 | ||||
-rw-r--r-- | libhb/sync.c | 19 | ||||
-rw-r--r-- | libhb/work.c | 3 | ||||
-rw-r--r-- | macosx/Controller.m | 62 | ||||
-rw-r--r-- | macosx/HBSubtitles.m | 187 |
12 files changed, 1449 insertions, 677 deletions
diff --git a/gtk/src/hb-backend.c b/gtk/src/hb-backend.c index 77282d2ee..737814c5d 100644 --- a/gtk/src/hb-backend.c +++ b/gtk/src/hb-backend.c @@ -4704,8 +4704,17 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, int titleindex) strncpy(sub_config.src_codeset, code, 39); sub_config.src_codeset[39] = 0; sub_config.force = 0; - sub_config.dest = PASSTHRUSUB; sub_config.default_track = def; + if (burned && !one_burned && hb_subtitle_can_burn(SRTSUB)) + { + // Only allow one subtitle to be burned into the video + sub_config.dest = RENDERSUB; + one_burned = TRUE; + } + else + { + sub_config.dest = PASSTHRUSUB; + } hb_srt_add( job, &sub_config, lang); @@ -4718,18 +4727,16 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, int titleindex) subtitle = ghb_settings_get_int(ssettings, "SubtitleTrack"); if (subtitle == -1) { - if (!burned) - { - job->select_subtitle_config.dest = PASSTHRUSUB; - } - else if (burned) + if (burned && !one_burned) { // Only allow one subtitle to be burned into the video - if (one_burned) - continue; job->select_subtitle_config.dest = RENDERSUB; one_burned = TRUE; } + else + { + job->select_subtitle_config.dest = PASSTHRUSUB; + } job->select_subtitle_config.force = force; job->select_subtitle_config.default_track = def; job->indepth_scan = 1; @@ -4744,18 +4751,16 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, int titleindex) if (subt != NULL) { sub_config = subt->config; - if (!burned) - { - sub_config.dest = PASSTHRUSUB; - } - else if (burned && hb_subtitle_can_burn(subt->source)) + if (burned && !one_burned && hb_subtitle_can_burn(subt->source)) { // Only allow one subtitle to be burned into the video - if (one_burned) - continue; sub_config.dest = RENDERSUB; one_burned = TRUE; } + else + { + sub_config.dest = PASSTHRUSUB; + } sub_config.force = force; sub_config.default_track = def; hb_subtitle_add( job, &sub_config, subtitle ); diff --git a/libhb/colormap.c b/libhb/colormap.c new file mode 100644 index 000000000..059166463 --- /dev/null +++ b/libhb/colormap.c @@ -0,0 +1,721 @@ +/* colormap.c + * + * Copyright (c) 2003-2014 HandBrake Team + * This file is part of the HandBrake source code + * Homepage: <http://handbrake.fr/>. + * It may be used under the terms of the GNU General Public License v2. + * For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html + */ + +#include <stdio.h> +#include <stdint.h> +#include <strings.h> +#include "colormap.h" + +typedef struct +{ + char *name; + uint32_t rgb; +} hb_colormap_t; + +static hb_colormap_t colormap[] = +{ + { "none", 0xFFFFFF }, + { "black", 0x000000 }, + { "white", 0xFFFFFF }, + { "red", 0xFF0000 }, + { "green", 0x00FF00 }, + { "blue", 0x0000FF }, + { "aliceblue", 0xF0F8FF }, + { "antiquewhite", 0xFAEBD7 }, + { "antiquewhite1", 0xFFEFDB }, + { "antiquewhite2", 0xEEDFCC }, + { "antiquewhite3", 0xCDC0B0 }, + { "antiquewhite4", 0x8B8378 }, + { "aqua", 0x00FFFF }, + { "aquamarine", 0x7FFFD4 }, + { "aquamarine1", 0x7FFFD4 }, + { "aquamarine2", 0x76EEC6 }, + { "aquamarine3", 0x66CDAA }, + { "aquamarine4", 0x458B74 }, + { "azure", 0xF0FFFF }, + { "azure1", 0xF0FFFF }, + { "azure2", 0xE0EEEE }, + { "azure3", 0xC1CDCD }, + { "azure4", 0x838B8B }, + { "beige", 0xF5F5DC }, + { "bisque", 0xFFE4C4 }, + { "bisque1", 0xFFE4C4 }, + { "bisque2", 0xEED5B7 }, + { "bisque3", 0xCDB79E }, + { "bisque4", 0x8B7D6B }, + { "black", 0x000000 }, + { "blanchedalmond", 0xFFEBCD }, + { "blue", 0x0000FF }, + { "blue1", 0x0000FF }, + { "blue2", 0x0000EE }, + { "blue3", 0x0000CD }, + { "blue4", 0x00008B }, + { "blueviolet", 0x8A2BE2 }, + { "brown", 0xA52A2A }, + { "brown1", 0xFF4040 }, + { "brown2", 0xEE3B3B }, + { "brown3", 0xCD3333 }, + { "brown4", 0x8B2323 }, + { "burlywood", 0xDEB887 }, + { "burlywood1", 0xFFD39B }, + { "burlywood2", 0xEEC591 }, + { "burlywood3", 0xCDAA7D }, + { "burlywood4", 0x8B7355 }, + { "cadetblue", 0x5F9EA0 }, + { "cadetblue", 0x5F9EA0 }, + { "cadetblue1", 0x98F5FF }, + { "cadetblue2", 0x8EE5EE }, + { "cadetblue3", 0x7AC5CD }, + { "cadetblue4", 0x53868B }, + { "chartreuse", 0x7FFF00 }, + { "chartreuse1", 0x7FFF00 }, + { "chartreuse2", 0x76EE00 }, + { "chartreuse3", 0x66CD00 }, + { "chartreuse4", 0x458B00 }, + { "chocolate", 0xD2691E }, + { "chocolate1", 0xFF7F24 }, + { "chocolate2", 0xEE7621 }, + { "chocolate3", 0xCD661D }, + { "chocolate4", 0x8B4513 }, + { "coral", 0xFF7F50 }, + { "coral1", 0xFF7256 }, + { "coral2", 0xEE6A50 }, + { "coral3", 0xCD5B45 }, + { "coral4", 0x8B3E2F }, + { "cornflowerblue", 0x6495ED }, + { "cornsilk", 0xFFF8DC }, + { "cornsilk1", 0xFFF8DC }, + { "cornsilk2", 0xEEE8CD }, + { "cornsilk3", 0xCDC8B1 }, + { "cornsilk4", 0x8B8878 }, + { "crimson", 0xDC143C }, + { "cyan", 0x00FFFF }, + { "cyan1", 0x00FFFF }, + { "cyan2", 0x00EEEE }, + { "cyan3", 0x00CDCD }, + { "cyan4", 0x008B8B }, + { "darkblue", 0x00008B }, + { "darkcyan", 0x008B8B }, + { "darkgoldenrod", 0xB8860B }, + { "darkgoldenrod1", 0xFFB90F }, + { "darkgoldenrod2", 0xEEAD0E }, + { "darkgoldenrod3", 0xCD950C }, + { "darkgoldenrod4", 0x8B6508 }, + { "darkgray", 0xA9A9A9 }, + { "darkgreen", 0x006400 }, + { "darkgrey", 0xA9A9A9 }, + { "darkkhaki", 0xBDB76B }, + { "darkmagenta", 0x8B008B }, + { "darkolivegreen", 0x556B2F }, + { "darkolivegreen1", 0xCAFF70 }, + { "darkolivegreen2", 0xBCEE68 }, + { "darkolivegreen3", 0xA2CD5A }, + { "darkolivegreen4", 0x6E8B3D }, + { "darkorange", 0xFF8C00 }, + { "darkorange1", 0xFF7F00 }, + { "darkorange2", 0xEE7600 }, + { "darkorange3", 0xCD6600 }, + { "darkorange4", 0x8B4500 }, + { "darkorchid", 0x9932CC }, + { "darkorchid1", 0xBF3EFF }, + { "darkorchid2", 0xB23AEE }, + { "darkorchid3", 0x9A32CD }, + { "darkorchid4", 0x68228B }, + { "darkred", 0x8B0000 }, + { "darksalmon", 0xE9967A }, + { "darkseagreen", 0x8FBC8F }, + { "darkseagreen1", 0xC1FFC1 }, + { "darkseagreen2", 0xB4EEB4 }, + { "darkseagreen3", 0x9BCD9B }, + { "darkseagreen4", 0x698B69 }, + { "darkslateblue", 0x483D8B }, + { "darkslategray", 0x2F4F4F }, + { "darkslategray1", 0x97FFFF }, + { "darkslategray2", 0x8DEEEE }, + { "darkslategray3", 0x79CDCD }, + { "darkslategray4", 0x528B8B }, + { "darkslategrey", 0x2F4F4F }, + { "darkturquoise", 0x00CED1 }, + { "darkviolet", 0x9400D3 }, + { "darkviolet", 0x9400D3 }, + { "deeppink", 0xFF1493 }, + { "deeppink1", 0xFF1493 }, + { "deeppink2", 0xEE1289 }, + { "deeppink3", 0xCD1076 }, + { "deeppink4", 0x8B0A50 }, + { "deepskyblue", 0x00BFFF }, + { "deepskyblue1", 0x00BFFF }, + { "deepskyblue2", 0x00B2EE }, + { "deepskyblue3", 0x009ACD }, + { "deepskyblue4", 0x00688B }, + { "dimgray", 0x696969 }, + { "dimgrey", 0x696969 }, + { "dodgerblue", 0x1E90FF }, + { "dodgerblue1", 0x1E90FF }, + { "dodgerblue2", 0x1C86EE }, + { "dodgerblue3", 0x1874CD }, + { "dodgerblue4", 0x104E8B }, + { "firebrick", 0xB22222 }, + { "firebrick1", 0xFF3030 }, + { "firebrick2", 0xEE2C2C }, + { "firebrick3", 0xCD2626 }, + { "firebrick4", 0x8B1A1A }, + { "floralwhite", 0xFFFAF0 }, + { "forestgreen", 0x228B22 }, + { "fractal", 0x808080 }, + { "fuchsia", 0xFF00FF }, + { "gainsboro", 0xDCDCDC }, + { "ghostwhite", 0xF8F8FF }, + { "gold", 0xFFD700 }, + { "gold1", 0xFFD700 }, + { "gold2", 0xEEC900 }, + { "gold3", 0xCDAD00 }, + { "gold4", 0x8B7500 }, + { "goldenrod", 0xDAA520 }, + { "goldenrod1", 0xFFC125 }, + { "goldenrod2", 0xEEB422 }, + { "goldenrod3", 0xCD9B1D }, + { "goldenrod4", 0x8B6914 }, + { "gray", 0x7E7E7E }, + { "gray", 0xBEBEBE }, + { "gray0", 0x000000 }, + { "gray1", 0x030303 }, + { "gray10", 0x1A1A1A }, + { "gray100", 0xFFFFFF }, + { "gray11", 0x1C1C1C }, + { "gray12", 0x1F1F1F }, + { "gray13", 0x212121 }, + { "gray14", 0x242424 }, + { "gray15", 0x262626 }, + { "gray16", 0x292929 }, + { "gray17", 0x2B2B2B }, + { "gray18", 0x2E2E2E }, + { "gray19", 0x303030 }, + { "gray2", 0x050505 }, + { "gray20", 0x333333 }, + { "gray21", 0x363636 }, + { "gray22", 0x383838 }, + { "gray23", 0x3B3B3B }, + { "gray24", 0x3D3D3D }, + { "gray25", 0x404040 }, + { "gray26", 0x424242 }, + { "gray27", 0x454545 }, + { "gray28", 0x474747 }, + { "gray29", 0x4A4A4A }, + { "gray3", 0x080808 }, + { "gray30", 0x4D4D4D }, + { "gray31", 0x4F4F4F }, + { "gray32", 0x525252 }, + { "gray33", 0x545454 }, + { "gray34", 0x575757 }, + { "gray35", 0x595959 }, + { "gray36", 0x5C5C5C }, + { "gray37", 0x5E5E5E }, + { "gray38", 0x616161 }, + { "gray39", 0x636363 }, + { "gray4", 0x0A0A0A }, + { "gray40", 0x666666 }, + { "gray41", 0x696969 }, + { "gray42", 0x6B6B6B }, + { "gray43", 0x6E6E6E }, + { "gray44", 0x707070 }, + { "gray45", 0x737373 }, + { "gray46", 0x757575 }, + { "gray47", 0x787878 }, + { "gray48", 0x7A7A7A }, + { "gray49", 0x7D7D7D }, + { "gray5", 0x0D0D0D }, + { "gray50", 0x7F7F7F }, + { "gray51", 0x828282 }, + { "gray52", 0x858585 }, + { "gray53", 0x878787 }, + { "gray54", 0x8A8A8A }, + { "gray55", 0x8C8C8C }, + { "gray56", 0x8F8F8F }, + { "gray57", 0x919191 }, + { "gray58", 0x949494 }, + { "gray59", 0x969696 }, + { "gray6", 0x0F0F0F }, + { "gray60", 0x999999 }, + { "gray61", 0x9C9C9C }, + { "gray62", 0x9E9E9E }, + { "gray63", 0xA1A1A1 }, + { "gray64", 0xA3A3A3 }, + { "gray65", 0xA6A6A6 }, + { "gray66", 0xA8A8A8 }, + { "gray67", 0xABABAB }, + { "gray68", 0xADADAD }, + { "gray69", 0xB0B0B0 }, + { "gray7", 0x121212 }, + { "gray70", 0xB3B3B3 }, + { "gray71", 0xB5B5B5 }, + { "gray72", 0xB8B8B8 }, + { "gray73", 0xBABABA }, + { "gray74", 0xBDBDBD }, + { "gray75", 0xBFBFBF }, + { "gray76", 0xC2C2C2 }, + { "gray77", 0xC4C4C4 }, + { "gray78", 0xC7C7C7 }, + { "gray79", 0xC9C9C9 }, + { "gray8", 0x141414 }, + { "gray80", 0xCCCCCC }, + { "gray81", 0xCFCFCF }, + { "gray82", 0xD1D1D1 }, + { "gray83", 0xD4D4D4 }, + { "gray84", 0xD6D6D6 }, + { "gray85", 0xD9D9D9 }, + { "gray86", 0xDBDBDB }, + { "gray87", 0xDEDEDE }, + { "gray88", 0xE0E0E0 }, + { "gray89", 0xE3E3E3 }, + { "gray9", 0x171717 }, + { "gray90", 0xE5E5E5 }, + { "gray91", 0xE8E8E8 }, + { "gray92", 0xEBEBEB }, + { "gray93", 0xEDEDED }, + { "gray94", 0xF0F0F0 }, + { "gray95", 0xF2F2F2 }, + { "gray96", 0xF5F5F5 }, + { "gray97", 0xF7F7F7 }, + { "gray98", 0xFAFAFA }, + { "gray99", 0xFCFCFC }, + { "green", 0x008000 }, + { "green", 0x00FF00 }, + { "green1", 0x00FF00 }, + { "green2", 0x00EE00 }, + { "green3", 0x00CD00 }, + { "green4", 0x008B00 }, + { "greenyellow", 0xADFF2F }, + { "grey", 0xBEBEBE }, + { "grey0", 0x000000 }, + { "grey1", 0x030303 }, + { "grey10", 0x1A1A1A }, + { "grey100", 0xFFFFFF }, + { "grey11", 0x1C1C1C }, + { "grey12", 0x1F1F1F }, + { "grey13", 0x212121 }, + { "grey14", 0x242424 }, + { "grey15", 0x262626 }, + { "grey16", 0x292929 }, + { "grey17", 0x2B2B2B }, + { "grey18", 0x2E2E2E }, + { "grey19", 0x303030 }, + { "grey2", 0x050505 }, + { "grey20", 0x333333 }, + { "grey21", 0x363636 }, + { "grey22", 0x383838 }, + { "grey23", 0x3B3B3B }, + { "grey24", 0x3D3D3D }, + { "grey25", 0x404040 }, + { "grey26", 0x424242 }, + { "grey27", 0x454545 }, + { "grey28", 0x474747 }, + { "grey29", 0x4A4A4A }, + { "grey3", 0x080808 }, + { "grey30", 0x4D4D4D }, + { "grey31", 0x4F4F4F }, + { "grey32", 0x525252 }, + { "grey33", 0x545454 }, + { "grey34", 0x575757 }, + { "grey35", 0x595959 }, + { "grey36", 0x5C5C5C }, + { "grey37", 0x5E5E5E }, + { "grey38", 0x616161 }, + { "grey39", 0x636363 }, + { "grey4", 0x0A0A0A }, + { "grey40", 0x666666 }, + { "grey41", 0x696969 }, + { "grey42", 0x6B6B6B }, + { "grey43", 0x6E6E6E }, + { "grey44", 0x707070 }, + { "grey45", 0x737373 }, + { "grey46", 0x757575 }, + { "grey47", 0x787878 }, + { "grey48", 0x7A7A7A }, + { "grey49", 0x7D7D7D }, + { "grey5", 0x0D0D0D }, + { "grey50", 0x7F7F7F }, + { "grey51", 0x828282 }, + { "grey52", 0x858585 }, + { "grey53", 0x878787 }, + { "grey54", 0x8A8A8A }, + { "grey55", 0x8C8C8C }, + { "grey56", 0x8F8F8F }, + { "grey57", 0x919191 }, + { "grey58", 0x949494 }, + { "grey59", 0x969696 }, + { "grey6", 0x0F0F0F }, + { "grey60", 0x999999 }, + { "grey61", 0x9C9C9C }, + { "grey62", 0x9E9E9E }, + { "grey63", 0xA1A1A1 }, + { "grey64", 0xA3A3A3 }, + { "grey65", 0xA6A6A6 }, + { "grey66", 0xA8A8A8 }, + { "grey67", 0xABABAB }, + { "grey68", 0xADADAD }, + { "grey69", 0xB0B0B0 }, + { "grey7", 0x121212 }, + { "grey70", 0xB3B3B3 }, + { "grey71", 0xB5B5B5 }, + { "grey72", 0xB8B8B8 }, + { "grey73", 0xBABABA }, + { "grey74", 0xBDBDBD }, + { "grey75", 0xBFBFBF }, + { "grey76", 0xC2C2C2 }, + { "grey77", 0xC4C4C4 }, + { "grey78", 0xC7C7C7 }, + { "grey79", 0xC9C9C9 }, + { "grey8", 0x141414 }, + { "grey80", 0xCCCCCC }, + { "grey81", 0xCFCFCF }, + { "grey82", 0xD1D1D1 }, + { "grey83", 0xD4D4D4 }, + { "grey84", 0xD6D6D6 }, + { "grey85", 0xD9D9D9 }, + { "grey86", 0xDBDBDB }, + { "grey87", 0xDEDEDE }, + { "grey88", 0xE0E0E0 }, + { "grey89", 0xE3E3E3 }, + { "grey9", 0x171717 }, + { "grey90", 0xE5E5E5 }, + { "grey91", 0xE8E8E8 }, + { "grey92", 0xEBEBEB }, + { "grey93", 0xEDEDED }, + { "grey94", 0xF0F0F0 }, + { "grey95", 0xF2F2F2 }, + { "grey96", 0xF5F5F5 }, + { "grey97", 0xF7F7F7 }, + { "grey98", 0xFAFAFA }, + { "grey99", 0xFCFCFC }, + { "honeydew", 0xF0FFF0 }, + { "honeydew1", 0xF0FFF0 }, + { "honeydew2", 0xE0EEE0 }, + { "honeydew3", 0xC1CDC1 }, + { "honeydew4", 0x838B83 }, + { "hotpink", 0xFF69B4 }, + { "hotpink1", 0xFF6EB4 }, + { "hotpink2", 0xEE6AA7 }, + { "hotpink3", 0xCD6090 }, + { "hotpink4", 0x8B3A62 }, + { "indianred", 0xCD5C5C }, + { "indianred1", 0xFF6A6A }, + { "indianred2", 0xEE6363 }, + { "indianred3", 0xCD5555 }, + { "indianred4", 0x8B3A3A }, + { "indigo", 0x4B0082 }, + { "ivory", 0xFFFFF0 }, + { "ivory1", 0xFFFFF0 }, + { "ivory2", 0xEEEEE0 }, + { "ivory3", 0xCDCDC1 }, + { "ivory4", 0x8B8B83 }, + { "khaki", 0xF0E68C }, + { "khaki1", 0xFFF68F }, + { "khaki2", 0xEEE685 }, + { "khaki3", 0xCDC673 }, + { "khaki4", 0x8B864E }, + { "lavender", 0xE6E6FA }, + { "lavenderblush", 0xFFF0F5 }, + { "lavenderblush1", 0xFFF0F5 }, + { "lavenderblush2", 0xEEE0E5 }, + { "lavenderblush3", 0xCDC1C5 }, + { "lavenderblush4", 0x8B8386 }, + { "lawngreen", 0x7CFC00 }, + { "lemonchiffon", 0xFFFACD }, + { "lemonchiffon1", 0xFFFACD }, + { "lemonchiffon2", 0xEEE9BF }, + { "lemonchiffon3", 0xCDC9A5 }, + { "lemonchiffon4", 0x8B8970 }, + { "lightblue", 0xADD8E6 }, + { "lightblue1", 0xBFEFFF }, + { "lightblue2", 0xB2DFEE }, + { "lightblue3", 0x9AC0CD }, + { "lightblue4", 0x68838B }, + { "lightcoral", 0xF08080 }, + { "lightcyan", 0xE0FFFF }, + { "lightcyan1", 0xE0FFFF }, + { "lightcyan2", 0xD1EEEE }, + { "lightcyan3", 0xB4CDCD }, + { "lightcyan4", 0x7A8B8B }, + { "lightgoldenrod", 0xEEDD82 }, + { "lightgoldenrod1", 0xFFEC8B }, + { "lightgoldenrod2", 0xEEDC82 }, + { "lightgoldenrod3", 0xCDBE70 }, + { "lightgoldenrod4", 0x8B814C }, + { "lightgoldenrodyellow", 0xFAFAD2 }, + { "lightgray", 0xD3D3D3 }, + { "lightgreen", 0x90EE90 }, + { "lightgrey", 0xD3D3D3 }, + { "lightpink", 0xFFB6C1 }, + { "lightpink1", 0xFFAEB9 }, + { "lightpink2", 0xEEA2AD }, + { "lightpink3", 0xCD8C95 }, + { "lightpink4", 0x8B5F65 }, + { "lightsalmon", 0xFFA07A }, + { "lightsalmon1", 0xFFA07A }, + { "lightsalmon2", 0xEE9572 }, + { "lightsalmon3", 0xCD8162 }, + { "lightsalmon4", 0x8B5742 }, + { "lightseagreen", 0x20B2AA }, + { "lightskyblue", 0x87CEFA }, + { "lightskyblue1", 0xB0E2FF }, + { "lightskyblue2", 0xA4D3EE }, + { "lightskyblue3", 0x8DB6CD }, + { "lightskyblue4", 0x607B8B }, + { "lightslateblue", 0x8470FF }, + { "lightslategray", 0x778899 }, + { "lightslategrey", 0x778899 }, + { "lightsteelblue", 0xB0C4DE }, + { "lightsteelblue1", 0xCAE1FF }, + { "lightsteelblue2", 0xBCD2EE }, + { "lightsteelblue3", 0xA2B5CD }, + { "lightsteelblue4", 0x6E7B8B }, + { "lightyellow", 0xFFFFE0 }, + { "lightyellow1", 0xFFFFE0 }, + { "lightyellow2", 0xEEEED1 }, + { "lightyellow3", 0xCDCDB4 }, + { "lightyellow4", 0x8B8B7A }, + { "lime", 0x00FF00 }, + { "limegreen", 0x32CD32 }, + { "linen", 0xFAF0E6 }, + { "magenta", 0xFF00FF }, + { "magenta1", 0xFF00FF }, + { "magenta2", 0xEE00EE }, + { "magenta3", 0xCD00CD }, + { "magenta4", 0x8B008B }, + { "maroon", 0x800000 }, + { "maroon", 0xB03060 }, + { "maroon1", 0xFF34B3 }, + { "maroon2", 0xEE30A7 }, + { "maroon3", 0xCD2990 }, + { "maroon4", 0x8B1C62 }, + { "mediumaquamarine", 0x66CDAA }, + { "mediumblue", 0x0000CD }, + { "mediumforestgreen", 0x32814B }, + { "mediumgoldenrod", 0xD1C166 }, + { "mediumorchid", 0xBA55D3 }, + { "mediumorchid1", 0xE066FF }, + { "mediumorchid2", 0xD15FEE }, + { "mediumorchid3", 0xB452CD }, + { "mediumorchid4", 0x7A378B }, + { "mediumpurple", 0x9370DB }, + { "mediumpurple1", 0xAB82FF }, + { "mediumpurple2", 0x9F79EE }, + { "mediumpurple3", 0x8968CD }, + { "mediumpurple4", 0x5D478B }, + { "mediumseagreen", 0x3CB371 }, + { "mediumslateblue", 0x7B68EE }, + { "mediumspringgreen", 0x00FA9A }, + { "mediumturquoise", 0x48D1CC }, + { "mediumvioletred", 0xC71585 }, + { "midnightblue", 0x191970 }, + { "mintcream", 0xF5FFFA }, + { "mistyrose", 0xFFE4E1 }, + { "mistyrose1", 0xFFE4E1 }, + { "mistyrose2", 0xEED5D2 }, + { "mistyrose3", 0xCDB7B5 }, + { "mistyrose4", 0x8B7D7B }, + { "moccasin", 0xFFE4B5 }, + { "navajowhite", 0xFFDEAD }, + { "navajowhite1", 0xFFDEAD }, + { "navajowhite2", 0xEECFA1 }, + { "navajowhite3", 0xCDB38B }, + { "navajowhite4", 0x8B795E }, + { "navy", 0x000080 }, + { "navyblue", 0x000080 }, + { "none", 0x0000FF }, + { "oldlace", 0xFDF5E6 }, + { "olive", 0x808000 }, + { "olivedrab", 0x6B8E23 }, + { "olivedrab1", 0xC0FF3E }, + { "olivedrab2", 0xB3EE3A }, + { "olivedrab3", 0x9ACD32 }, + { "olivedrab4", 0x698B22 }, + { "opaque", 0x000000 }, + { "orange", 0xFFA500 }, + { "orange1", 0xFFA500 }, + { "orange2", 0xEE9A00 }, + { "orange3", 0xCD8500 }, + { "orange4", 0x8B5A00 }, + { "orangered", 0xFF4500 }, + { "orangered1", 0xFF4500 }, + { "orangered2", 0xEE4000 }, + { "orangered3", 0xCD3700 }, + { "orangered4", 0x8B2500 }, + { "orchid", 0xDA70D6 }, + { "orchid1", 0xFF83FA }, + { "orchid2", 0xEE7AE9 }, + { "orchid3", 0xCD69C9 }, + { "orchid4", 0x8B4789 }, + { "palegoldenrod", 0xEEE8AA }, + { "palegreen", 0x98FB98 }, + { "palegreen1", 0x9AFF9A }, + { "palegreen2", 0x90EE90 }, + { "palegreen3", 0x7CCD7C }, + { "palegreen4", 0x548B54 }, + { "paleturquoise", 0xAFEEEE }, + { "paleturquoise1", 0xBBFFFF }, + { "paleturquoise2", 0xAEEEEE }, + { "paleturquoise3", 0x96CDCD }, + { "paleturquoise4", 0x668B8B }, + { "palevioletred", 0xDB7093 }, + { "palevioletred1", 0xFF82AB }, + { "palevioletred2", 0xEE799F }, + { "palevioletred3", 0xCD6889 }, + { "palevioletred4", 0x8B475D }, + { "papayawhip", 0xFFEFD5 }, + { "peachpuff", 0xFFDAB9 }, + { "peachpuff1", 0xFFDAB9 }, + { "peachpuff2", 0xEECBAD }, + { "peachpuff3", 0xCDAF95 }, + { "peachpuff4", 0x8B7765 }, + { "peru", 0xCD853F }, + { "pink", 0xFFC0CB }, + { "pink1", 0xFFB5C5 }, + { "pink2", 0xEEA9B8 }, + { "pink3", 0xCD919E }, + { "pink4", 0x8B636C }, + { "plum", 0xDDA0DD }, + { "plum1", 0xFFBBFF }, + { "plum2", 0xEEAEEE }, + { "plum3", 0xCD96CD }, + { "plum4", 0x8B668B }, + { "powderblue", 0xB0E0E6 }, + { "purple", 0x800080 }, + { "purple", 0xA020F0 }, + { "purple1", 0x9B30FF }, + { "purple2", 0x912CEE }, + { "purple3", 0x7D26CD }, + { "purple4", 0x551A8B }, + { "red", 0xFF0000 }, + { "red1", 0xFF0000 }, + { "red2", 0xEE0000 }, + { "red3", 0xCD0000 }, + { "red4", 0x8B0000 }, + { "rosybrown", 0xBC8F8F }, + { "rosybrown1", 0xFFC1C1 }, + { "rosybrown2", 0xEEB4B4 }, + { "rosybrown3", 0xCD9B9B }, + { "rosybrown4", 0x8B6969 }, + { "royalblue", 0x4169E1 }, + { "royalblue1", 0x4876FF }, + { "royalblue2", 0x436EEE }, + { "royalblue3", 0x3A5FCD }, + { "royalblue4", 0x27408B }, + { "saddlebrown", 0x8B4513 }, + { "salmon", 0xFA8072 }, + { "salmon1", 0xFF8C69 }, + { "salmon2", 0xEE8262 }, + { "salmon3", 0xCD7054 }, + { "salmon4", 0x8B4C39 }, + { "sandybrown", 0xF4A460 }, + { "seagreen", 0x2E8B57 }, + { "seagreen1", 0x54FF9F }, + { "seagreen2", 0x4EEE94 }, + { "seagreen3", 0x43CD80 }, + { "seagreen4", 0x2E8B57 }, + { "seashell", 0xFFF5EE }, + { "seashell1", 0xFFF5EE }, + { "seashell2", 0xEEE5DE }, + { "seashell3", 0xCDC5BF }, + { "seashell4", 0x8B8682 }, + { "sienna", 0xA0522D }, + { "sienna1", 0xFF8247 }, + { "sienna2", 0xEE7942 }, + { "sienna3", 0xCD6839 }, + { "sienna4", 0x8B4726 }, + { "silver", 0xC0C0C0 }, + { "skyblue", 0x87CEEB }, + { "skyblue1", 0x87CEFF }, + { "skyblue2", 0x7EC0EE }, + { "skyblue3", 0x6CA6CD }, + { "skyblue4", 0x4A708B }, + { "slateblue", 0x6A5ACD }, + { "slateblue1", 0x836FFF }, + { "slateblue2", 0x7A67EE }, + { "slateblue3", 0x6959CD }, + { "slateblue4", 0x473C8B }, + { "slategray", 0x708090 }, + { "slategray1", 0xC6E2FF }, + { "slategray2", 0xB9D3EE }, + { "slategray3", 0x9FB6CD }, + { "slategray4", 0x6C7B8B }, + { "slategrey", 0x708090 }, + { "snow", 0xFFFAFA }, + { "snow1", 0xFFFAFA }, + { "snow2", 0xEEE9E9 }, + { "snow3", 0xCDC9C9 }, + { "snow4", 0x8B8989 }, + { "springgreen", 0x00FF7F }, + { "springgreen1", 0x00FF7F }, + { "springgreen2", 0x00EE76 }, + { "springgreen3", 0x00CD66 }, + { "springgreen4", 0x008B45 }, + { "steelblue", 0x4682B4 }, + { "steelblue1", 0x63B8FF }, + { "steelblue2", 0x5CACEE }, + { "steelblue3", 0x4F94CD }, + { "steelblue4", 0x36648B }, + { "tan", 0xD2B48C }, + { "tan1", 0xFFA54F }, + { "tan2", 0xEE9A49 }, + { "tan3", 0xCD853F }, + { "tan4", 0x8B5A2B }, + { "teal", 0x008080 }, + { "thistle", 0xD8BFD8 }, + { "thistle1", 0xFFE1FF }, + { "thistle2", 0xEED2EE }, + { "thistle3", 0xCDB5CD }, + { "thistle4", 0x8B7B8B }, + { "tomato", 0xFF6347 }, + { "tomato1", 0xFF6347 }, + { "tomato2", 0xEE5C42 }, + { "tomato3", 0xCD4F39 }, + { "tomato4", 0x8B3626 }, + { "transparent", 0x0000FF }, + { "turquoise", 0x40E0D0 }, + { "turquoise1", 0x00F5FF }, + { "turquoise2", 0x00E5EE }, + { "turquoise3", 0x00C5CD }, + { "turquoise4", 0x00868B }, + { "violet", 0xEE82EE }, + { "violetred", 0xD02090 }, + { "violetred1", 0xFF3E96 }, + { "violetred2", 0xEE3A8C }, + { "violetred3", 0xCD3278 }, + { "violetred4", 0x8B2252 }, + { "wheat", 0xF5DEB3 }, + { "wheat1", 0xFFE7BA }, + { "wheat2", 0xEED8AE }, + { "wheat3", 0xCDBA96 }, + { "wheat4", 0x8B7E66 }, + { "white", 0xFFFFFF }, + { "whitesmoke", 0xF5F5F5 }, + { "yellow", 0xFFFF00 }, + { "yellow1", 0xFFFF00 }, + { "yellow2", 0xEEEE00 }, + { "yellow3", 0xCDCD00 }, + { "yellow4", 0x8B8B00 }, + { "yellowgreen", 0x9ACD32 }, + { NULL, 0x000000 } +}; + +uint32_t hb_rgb_lookup_by_name(const char *color) +{ + int ii = 0; + + while (colormap[ii].name != NULL) + { + if (!strcasecmp(color, colormap[ii].name)) + return colormap[ii].rgb; + ii++; + } + return 0; +} + diff --git a/libhb/colormap.h b/libhb/colormap.h new file mode 100644 index 000000000..ab049aa0b --- /dev/null +++ b/libhb/colormap.h @@ -0,0 +1,20 @@ +/* colormap.h + * + * Copyright (c) 2003-2014 HandBrake Team + * This file is part of the HandBrake source code + * Homepage: <http://handbrake.fr/>. + * It may be used under the terms of the GNU General Public License v2. + * For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html + */ + +#ifndef HB_COLORMAP_H +#define HB_COLORMAP_H + +#define HB_RGB_TO_BGR(c) (((c & 0xff0000) >> 16) | \ + ((c & 0x00ff00) ) | \ + ((c & 0x0000ff) << 16)) +#define HB_BGR_TO_RGB(c) HB_RGB_TO_BGR(c) + +uint32_t hb_rgb_lookup_by_name(const char *color); + +#endif // HB_COLORMAP_H diff --git a/libhb/common.c b/libhb/common.c index 8f206c69f..b689facd4 100644 --- a/libhb/common.c +++ b/libhb/common.c @@ -3728,7 +3728,6 @@ int hb_srt_add( const hb_job_t * job, strncpy( subtitle->iso639_2, lang, 4 ); subtitle->config = *subtitlecfg; - subtitle->config.dest = PASSTHRUSUB; hb_list_add(job->list_subtitle, subtitle); retval = 1; @@ -3743,7 +3742,9 @@ int hb_subtitle_can_force( int source ) int hb_subtitle_can_burn( int source ) { - return source == VOBSUB || source == PGSSUB || source == SSASUB; + return source == VOBSUB || source == PGSSUB || source == SSASUB || + source == SRTSUB || source == CC608SUB || source == UTF8SUB || + source == TX3GSUB; } int hb_subtitle_can_pass( int source, int mux ) diff --git a/libhb/deccc608sub.c b/libhb/deccc608sub.c index c18fa76b8..d732ae21e 100644 --- a/libhb/deccc608sub.c +++ b/libhb/deccc608sub.c @@ -1,5 +1,5 @@ /* - * From ccextractor, leave this file as intact and close to the original as possible so that + * From ccextractor, leave this file as intact and close to the original as possible so that * it is easy to patch in fixes - even though this file contains code that we don't need. * * Note that the SRT sub generation from CC could be useful for mkv subs. @@ -15,13 +15,9 @@ static int trim_subs = 1; static int nofontcolor = 0; static enum encoding_type encoding = ENC_UTF_8; static int cc_channel = 1; -static enum output_format write_format = OF_SRT; static int sentence_cap = 0; static int subs_delay = 0; -static int64_t screens_to_process = -1; -static int processed_enough = 0; -static int gui_mode_reports = 0; -static int norollup = 1; +static int norollup = 0; static int direct_rollup = 0; /* @@ -33,14 +29,13 @@ static int64_t get_fts(struct s_write *wb) } #define fatal(N, ...) // N -#define XMLRPC_APPEND(N, ...) // N int rowdata[] = {11,-1,1,2,3,4,12,13,14,15,5,6,7,8,9,10}; // Relationship between the first PAC byte and the row number // The following enc_buffer is not used at the moment, if it does get used // we need to bring it into the swrite struct. Same for "str". -#define INITIAL_ENC_BUFFER_CAPACITY 2048 +#define INITIAL_ENC_BUFFER_CAPACITY 2048 unsigned char str[2048]; // Another generic general purpose buffer @@ -51,7 +46,7 @@ unsigned char str[2048]; // Another generic general purpose buffer const unsigned char pac2_attribs[][3]= // Color, font, ident { - {COL_WHITE, FONT_REGULAR, 0}, // 0x40 || 0x60 + {COL_WHITE, FONT_REGULAR, 0}, // 0x40 || 0x60 {COL_WHITE, FONT_UNDERLINED, 0}, // 0x41 || 0x61 {COL_GREEN, FONT_REGULAR, 0}, // 0x42 || 0x62 {COL_GREEN, FONT_UNDERLINED, 0}, // 0x43 || 0x63 @@ -86,7 +81,7 @@ const unsigned char pac2_attribs[][3]= // Color, font, ident }; // Preencoded strings -unsigned char encoded_crlf[16]; +unsigned char encoded_crlf[16]; unsigned int encoded_crlf_length; unsigned char encoded_br[16]; unsigned int encoded_br_length; @@ -95,19 +90,6 @@ unsigned int encoded_br_length; unsigned char usercolor_rgb[8]=""; enum color_code default_color=COL_WHITE; -const char *sami_header= // TODO: Revise the <!-- comments -"<SAMI>\n\ -<HEAD>\n\ -<STYLE TYPE=\"text/css\">\n\ -<!--\n\ -P {margin-left: 16pt; margin-right: 16pt; margin-bottom: 16pt; margin-top: 16pt;\n\ -text-align: center; font-size: 18pt; font-family: arial; font-weight: bold; color: #f0f0f0;}\n\ -.UNKNOWNCC {Name:Unknown; lang:en-US; SAMIType:CC;}\n\ --->\n\ -</STYLE>\n\ -</HEAD>\n\n\ -<BODY>\n"; - const char *command_type[] = { "Unknown", @@ -155,7 +137,7 @@ int general_608_init (struct s_write *wb) { if( !wb->enc_buffer ) { - wb->enc_buffer=(unsigned char *) malloc (INITIAL_ENC_BUFFER_CAPACITY); + wb->enc_buffer=(unsigned char *) malloc (INITIAL_ENC_BUFFER_CAPACITY); if (wb->enc_buffer==NULL) return -1; wb->enc_buffer_capacity=INITIAL_ENC_BUFFER_CAPACITY; @@ -163,7 +145,7 @@ int general_608_init (struct s_write *wb) if( !wb->subline) { wb->subline = malloc(2048); - + if (!wb->subline) { return -1; @@ -207,8 +189,8 @@ void general_608_close (struct s_write *wb) void get_char_in_latin_1 (unsigned char *buffer, unsigned char c) { unsigned char c1='?'; - if (c<0x80) - { + if (c<0x80) + { // Regular line-21 character set, mostly ASCII except these exceptions switch (c) { @@ -220,7 +202,7 @@ void get_char_in_latin_1 (unsigned char *buffer, unsigned char c) break; case 0x5e: // lowercase i, acute accent c1=0xed; - break; + break; case 0x5f: // lowercase o, acute accent c1=0xf3; break; @@ -249,25 +231,25 @@ void get_char_in_latin_1 (unsigned char *buffer, unsigned char c) switch (c) { // THIS BLOCK INCLUDES THE 16 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS - // THAT COME FROM HI BYTE=0x11 AND LOW BETWEEN 0x30 AND 0x3F + // THAT COME FROM HI BYTE=0x11 AND LOW BETWEEN 0x30 AND 0x3F case 0x80: // Registered symbol (R) c1=0xae; - break; + break; case 0x81: // degree sign c1=0xb0; break; - case 0x82: // 1/2 symbol + case 0x82: // 1/2 symbol c1=0xbd; break; - case 0x83: // Inverted (open) question mark + case 0x83: // Inverted (open) question mark c1=0xbf; break; case 0x84: // Trademark symbol (TM) - Does not exist in Latin 1 - break; - case 0x85: // Cents symbol + break; + case 0x85: // Cents symbol c1=0xa2; break; - case 0x86: // Pounds sterling + case 0x86: // Pounds sterling c1=0xa3; break; case 0x87: // Music note - Not in latin 1, so we use 'pilcrow' @@ -277,7 +259,7 @@ void get_char_in_latin_1 (unsigned char *buffer, unsigned char c) c1=0xe0; break; case 0x89: // transparent space, we make it regular - c1=0x20; + c1=0x20; break; case 0x8a: // lowercase e, grave accent c1=0xe8; @@ -286,7 +268,7 @@ void get_char_in_latin_1 (unsigned char *buffer, unsigned char c) c1=0xe2; break; case 0x8c: // lowercase e, circumflex accent - c1=0xea; + c1=0xea; break; case 0x8d: // lowercase i, circumflex accent c1=0xee; @@ -318,19 +300,19 @@ void get_char_in_latin_1 (unsigned char *buffer, unsigned char c) c1=0xfc; break; case 0x96: // apostrophe - c1=0x27; + c1=0x27; break; - case 0x97: // inverted exclamation mark + case 0x97: // inverted exclamation mark c1=0xa1; break; case 0x98: // asterisk - c1=0x2a; + c1=0x2a; break; case 0x99: // apostrophe (yes, duped). See CCADI source code. - c1=0x27; + c1=0x27; break; case 0x9a: // hyphen-minus - c1=0x2d; + c1=0x2d; break; case 0x9b: // copyright sign c1=0xa9; @@ -341,17 +323,17 @@ void get_char_in_latin_1 (unsigned char *buffer, unsigned char c) c1=0x2e; break; case 0x9e: // Quoatation mark - c1=0x22; + c1=0x22; break; case 0x9f: // Quoatation mark - c1=0x22; + c1=0x22; break; case 0xa0: // uppercase A, grave accent c1=0xc0; break; case 0xa1: // uppercase A, circumflex c1=0xc2; - break; + break; case 0xa2: // uppercase C with cedilla c1=0xc7; break; @@ -427,7 +409,7 @@ void get_char_in_latin_1 (unsigned char *buffer, unsigned char c) c1=0x7b; break; case 0xba: // Closing curly brace - c1=0x7d; + c1=0x7d; break; case 0xbb: // Backslash c1=0x5c; @@ -438,17 +420,17 @@ void get_char_in_latin_1 (unsigned char *buffer, unsigned char c) case 0xbd: // Underscore c1=0x5f; break; - case 0xbe: // Pipe (broken bar) + case 0xbe: // Pipe (broken bar) c1=0xa6; break; case 0xbf: // Tilde - c1=0x7e; + c1=0x7e; break; - case 0xc0: // Uppercase A, umlaut + case 0xc0: // Uppercase A, umlaut c1=0xc4; break; case 0xc1: // Lowercase A, umlaut - c1=0xe3; + c1=0xe3; break; case 0xc2: // Uppercase O, umlaut c1=0xd6; @@ -464,10 +446,10 @@ void get_char_in_latin_1 (unsigned char *buffer, unsigned char c) break; case 0xc6: // Currency symbol c1=0xa4; - break; + break; case 0xc7: // Vertical bar c1=0x7c; - break; + break; case 0xc8: // Uppercase A, ring c1=0xc5; break; @@ -488,7 +470,7 @@ void get_char_in_latin_1 (unsigned char *buffer, unsigned char c) *buffer='?'; // I'll do it eventually, I promise break; // This are weird chars anyway } - *buffer=c1; + *buffer=c1; } void get_char_in_unicode (unsigned char *buffer, unsigned char c) @@ -496,7 +478,7 @@ void get_char_in_unicode (unsigned char *buffer, unsigned char c) unsigned char c1,c2; switch (c) { - case 0x84: // Trademark symbol (TM) + case 0x84: // Trademark symbol (TM) c2=0x21; c1=0x22; break; @@ -511,7 +493,7 @@ void get_char_in_unicode (unsigned char *buffer, unsigned char c) case 0xcc: // Upper left corner c2=0x23; c1=0x1c; - break; + break; case 0xcd: // Upper right corner c2=0x23; c1=0x1d; @@ -524,7 +506,7 @@ void get_char_in_unicode (unsigned char *buffer, unsigned char c) c2=0x23; c1=0x1f; break; - default: // Everything else, same as latin-1 followed by 00 + default: // Everything else, same as latin-1 followed by 00 get_char_in_latin_1 (&c1,c); c2=0; break; @@ -585,10 +567,10 @@ int get_char_in_utf_8 (unsigned char *buffer, unsigned char c) // Returns number switch (c) { // THIS BLOCK INCLUDES THE 16 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS - // THAT COME FROM HI BYTE=0x11 AND LOW BETWEEN 0x30 AND 0x3F + // THAT COME FROM HI BYTE=0x11 AND LOW BETWEEN 0x30 AND 0x3F case 0x80: // Registered symbol (R) *buffer=0xc2; - *(buffer+1)=0xae; + *(buffer+1)=0xae; return 2; case 0x81: // degree sign *buffer=0xc2; @@ -615,7 +597,7 @@ int get_char_in_utf_8 (unsigned char *buffer, unsigned char c) // Returns number *buffer=0xc2; *(buffer+1)=0xa3; return 2; - case 0x87: // Music note + case 0x87: // Music note *buffer=0xe2; *(buffer+1)=0x99; *(buffer+2)=0xaa; @@ -625,7 +607,7 @@ int get_char_in_utf_8 (unsigned char *buffer, unsigned char c) // Returns number *(buffer+1)=0xa0; return 2; case 0x89: // transparent space, we make it regular - *buffer=0x20; + *buffer=0x20; return 1; case 0x8a: // lowercase e, grave accent *buffer=0xc3; @@ -678,38 +660,38 @@ int get_char_in_utf_8 (unsigned char *buffer, unsigned char c) // Returns number *(buffer+1)=0xbc; return 2; case 0x96: // apostrophe - *buffer=0x27; + *buffer=0x27; return 1; case 0x97: // inverted exclamation mark *buffer=0xc2; *(buffer+1)=0xa1; return 2; case 0x98: // asterisk - *buffer=0x2a; + *buffer=0x2a; return 1; case 0x99: // apostrophe (yes, duped). See CCADI source code. - *buffer=0x27; + *buffer=0x27; return 1; case 0x9a: // hyphen-minus - *buffer=0x2d; + *buffer=0x2d; return 1; case 0x9b: // copyright sign *buffer=0xc2; *(buffer+1)=0xa9; return 2; - case 0x9c: // Service mark - *buffer=0xe2; + case 0x9c: // Service mark + *buffer=0xe2; *(buffer+1)=0x84; *(buffer+2)=0xa0; return 3; case 0x9d: // Full stop (.) - *buffer=0x2e; + *buffer=0x2e; return 1; case 0x9e: // Quoatation mark - *buffer=0x22; + *buffer=0x22; return 1; case 0x9f: // Quoatation mark - *buffer=0x22; + *buffer=0x22; return 1; case 0xa0: // uppercase A, grave accent *buffer=0xc3; @@ -817,7 +799,7 @@ int get_char_in_utf_8 (unsigned char *buffer, unsigned char c) // Returns number *buffer=0x7b; return 1; case 0xba: // Closing curly brace - *buffer=0x7d; + *buffer=0x7d; return 1; case 0xbb: // Backslash *buffer=0x5c; @@ -829,26 +811,26 @@ int get_char_in_utf_8 (unsigned char *buffer, unsigned char c) // Returns number *buffer=0x5f; return 1; case 0xbe: // Pipe (broken bar) - *buffer=0xc2; + *buffer=0xc2; *(buffer+1)=0xa6; return 1; case 0xbf: // Tilde *buffer=0x7e; // Not sure return 1; case 0xc0: // Uppercase A, umlaut - *buffer=0xc3; + *buffer=0xc3; *(buffer+1)=0x84; return 2; case 0xc1: // Lowercase A, umlaut - *buffer=0xc3; + *buffer=0xc3; *(buffer+1)=0xa4; return 2; case 0xc2: // Uppercase O, umlaut - *buffer=0xc3; + *buffer=0xc3; *(buffer+1)=0x96; return 2; case 0xc3: // Lowercase o, umlaut - *buffer=0xc3; + *buffer=0xc3; *(buffer+1)=0xb6; return 2; case 0xc4: // Esszett (sharp S) @@ -864,7 +846,7 @@ int get_char_in_utf_8 (unsigned char *buffer, unsigned char c) // Returns number *(buffer+1)=0xa4; return 2; case 0xc7: // Vertical bar - *buffer=0x7c; + *buffer=0x7c; return 1; case 0xc8: // Uppercase A, ring *buffer=0xc3; @@ -902,7 +884,7 @@ int get_char_in_utf_8 (unsigned char *buffer, unsigned char c) // Returns number *(buffer+1)=0x8c; *(buffer+2)=0x9f; return 3; - default: // + default: // *buffer='?'; // I'll do it eventually, I promise return 1; // This are weird chars anyway } @@ -919,35 +901,35 @@ unsigned char cctolower (unsigned char c) case 0x90: // capital letter A with acute return 0x2a; case 0x91: // capital letter E with acute - return 0x5c; + return 0x5c; case 0x92: // capital letter O with acute - return 0x5f; + return 0x5f; case 0x93: // capital letter U with acute - return 0x60; + return 0x60; case 0xa2: // uppercase C with cedilla - return 0x7b; + return 0x7b; case 0xa0: // uppercase A, grave accent - return 0x88; + return 0x88; case 0xa3: // uppercase E, grave accent - return 0x8a; + return 0x8a; case 0xa1: // uppercase A, circumflex - return 0x8b; + return 0x8b; case 0xa4: // uppercase E, circumflex - return 0x8c; + return 0x8c; case 0xa7: // uppercase I, circumflex - return 0x8d; + return 0x8d; case 0xaa: // uppercase O, circumflex - return 0x8e; + return 0x8e; case 0xad: // uppercase U, circumflex - return 0x8f; + return 0x8f; case 0x94: // capital letter U with diaresis - return 0x95; + return 0x95; case 0xa5: // capital letter E with diaresis - return 0xa6; + return 0xa6; case 0xa8: // uppercase I, with diaresis - return 0xa9; + return 0xa9; case 0xab: // uppercase U, grave accent - return 0xac; + return 0xac; case 0xb0: // Uppercase A, tilde return 0xb1; case 0xb2: // Uppercase I, acute accent @@ -1013,21 +995,21 @@ unsigned char cctoupper (unsigned char c) case 0xac: // lowercase u, grave accent return 0xab; case 0xb1: // Lowercase a, tilde - return 0xb0; + return 0xb0; case 0xb4: // Lowercase i, grave accent return 0xb3; case 0xb6: // Lowercase o, grave accent - return 0xb5; - case 0xb8: // Lowercase o, tilde + return 0xb5; + case 0xb8: // Lowercase o, tilde return 0xb7; - case 0xc1: // Lowercase A, umlaut - return 0xc0; + case 0xc1: // Lowercase A, umlaut + return 0xc0; case 0xc3: // Lowercase o, umlaut return 0xc2; case 0xc9: // Lowercase A, ring - return 0xc8; + return 0xc8; case 0xcb: // Lowercase o, slash - return 0xca; + return 0xca; } return c; } @@ -1035,12 +1017,12 @@ unsigned char cctoupper (unsigned char c) // Encodes a generic string. Note that since we use the encoders for closed caption // data, text would have to be encoded as CCs... so using special characters here -// it's a bad idea. +// it's a bad idea. unsigned encode_line (unsigned char *buffer, unsigned char *text) -{ +{ unsigned bytes=0; while (*text) - { + { switch (encoding) { case ENC_UTF_8: @@ -1049,13 +1031,13 @@ unsigned encode_line (unsigned char *buffer, unsigned char *text) bytes++; buffer++; break; - case ENC_UNICODE: - *buffer=*text; + case ENC_UNICODE: + *buffer=*text; *(buffer+1)=0; - bytes+=2; + bytes+=2; buffer+=2; break; - } + } text++; } return bytes; @@ -1086,7 +1068,7 @@ void correct_case (int line_num, struct eia608_screen *data) /* if (c-(char *) data->characters[line_num]+len==CC608_SCREEN_WIDTH) // End of line... */ /* next=' '; // ... pretend we have a blank later */ /* else */ -/* next=*(c+len); */ +/* next=*(c+len); */ /* if ( ISSEPARATOR(prev) && ISSEPARATOR(next)) */ /* { */ /* memcpy (c,spell_correct[i],len); */ @@ -1105,10 +1087,10 @@ void capitalize (int line_num, struct eia608_screen *data, int *new_sentence) { switch (data->characters[line_num][i]) { - case ' ': + case ' ': case 0x89: // This is a transparent space case '-': - break; + break; case '.': // Fallthrough case '?': // Fallthrough case '!': @@ -1116,7 +1098,7 @@ void capitalize (int line_num, struct eia608_screen *data, int *new_sentence) *new_sentence=1; break; default: - if (*new_sentence) + if (*new_sentence) data->characters[line_num][i]=cctoupper (data->characters[line_num][i]); else data->characters[line_num][i]=cctolower (data->characters[line_num][i]); @@ -1174,7 +1156,7 @@ unsigned get_decoder_line_basic (unsigned char *buffer, int line_num, struct eia break; case ENC_UNICODE: get_char_in_unicode (buffer,c); - bytes=2; + bytes=2; break; } buffer+=bytes; @@ -1183,38 +1165,20 @@ unsigned get_decoder_line_basic (unsigned char *buffer, int line_num, struct eia return (unsigned) (buffer-orig); // Return length } -unsigned get_decoder_line_encoded_for_gui (unsigned char *buffer, int line_num, struct eia608_screen *data) -{ - unsigned char *line = data->characters[line_num]; - unsigned char *orig=buffer; // Keep for debugging - int first=0, last=31; - int i; - - find_limit_characters(line,&first,&last); - for (i=first;i<=last;i++) - { - get_char_in_latin_1 (buffer,line[i]); - buffer++; - } - *buffer=0; - return (unsigned) (buffer-orig); // Return length - -} - unsigned get_decoder_line_encoded (unsigned char *buffer, int line_num, struct eia608_screen *data) { int col = COL_WHITE; int underlined = 0; - int italics = 0; + int italics = 0; int i; - unsigned char *line = data->characters[line_num]; + unsigned char *line = data->characters[line_num]; unsigned char *orig=buffer; // Keep for debugging int first=0, last=31; if (trim_subs) find_limit_characters(line,&first,&last); for (i=first;i<=last;i++) - { + { // Handle color int its_col = data->colors[line_num][i]; if (its_col != col && !nofontcolor) @@ -1227,11 +1191,11 @@ unsigned get_decoder_line_encoded (unsigned char *buffer, int line_num, struct e buffer+=encode_line (buffer, (unsigned char*) color_text[its_col][1]); if (its_col==COL_USERDEFINED) { - // The previous sentence doesn't copy the whole + // The previous sentence doesn't copy the whole // <font> tag, just up to the quote before the color buffer+=encode_line (buffer, (unsigned char*) usercolor_rgb); buffer+=encode_line (buffer, (unsigned char*) "\">"); - } + } col = its_col; } @@ -1244,10 +1208,10 @@ unsigned get_decoder_line_encoded (unsigned char *buffer, int line_num, struct e if (is_underlined==0 && underlined) // Close underline { buffer+=encode_line (buffer, (unsigned char *) "</u>"); - } + } underlined=is_underlined; // Handle italics - int has_ita = data->fonts[line_num][i] & FONT_ITALICS; + int has_ita = data->fonts[line_num][i] & FONT_ITALICS; if (has_ita && italics==0) // Open italics { buffer+=encode_line (buffer, (unsigned char *) "<i>"); @@ -1255,7 +1219,7 @@ unsigned get_decoder_line_encoded (unsigned char *buffer, int line_num, struct e if (has_ita==0 && italics) // Close italics { buffer+=encode_line (buffer, (unsigned char *) "</i>"); - } + } italics=has_ita; int bytes=0; switch (encoding) @@ -1269,10 +1233,10 @@ unsigned get_decoder_line_encoded (unsigned char *buffer, int line_num, struct e break; case ENC_UNICODE: get_char_in_unicode (buffer,line[i]); - bytes=2; + bytes=2; break; } - buffer+=bytes; + buffer+=bytes; } if (italics) { @@ -1299,10 +1263,10 @@ void delete_all_lines_but_current (struct eia608_screen *data, int row) if (i!=row) { memset(data->characters[i],' ',CC608_SCREEN_WIDTH); - data->characters[i][CC608_SCREEN_WIDTH]=0; - memset (data->colors[i],default_color,CC608_SCREEN_WIDTH+1); - memset (data->fonts[i],FONT_REGULAR,CC608_SCREEN_WIDTH+1); - data->row_used[i]=0; + data->characters[i][CC608_SCREEN_WIDTH]=0; + memset (data->colors[i],default_color,CC608_SCREEN_WIDTH+1); + memset (data->fonts[i],FONT_REGULAR,CC608_SCREEN_WIDTH+1); + data->row_used[i]=0; } } } @@ -1314,10 +1278,10 @@ void clear_eia608_cc_buffer (struct eia608_screen *data) for (i=0;i<15;i++) { memset(data->characters[i],' ',CC608_SCREEN_WIDTH); - data->characters[i][CC608_SCREEN_WIDTH]=0; - memset (data->colors[i],default_color,CC608_SCREEN_WIDTH+1); - memset (data->fonts[i],FONT_REGULAR,CC608_SCREEN_WIDTH+1); - data->row_used[i]=0; + data->characters[i][CC608_SCREEN_WIDTH]=0; + memset (data->colors[i],default_color,CC608_SCREEN_WIDTH+1); + memset (data->fonts[i],FONT_REGULAR,CC608_SCREEN_WIDTH+1); + data->row_used[i]=0; } data->empty=1; } @@ -1336,33 +1300,52 @@ void init_eia608 (struct eia608 *data) data->current_visible_start_ms=0; data->srt_counter=0; data->screenfuls_counter=0; - data->channel=1; + data->channel=1; data->color=default_color; data->font=FONT_REGULAR; data->rollup_base_row=14; } +struct eia608_screen *get_current_hidden_buffer(struct s_write *wb) +{ + struct eia608_screen *data; + if (wb->data608->visible_buffer == 1) + data = &wb->data608->buffer2; + else + data = &wb->data608->buffer1; + return data; +} + +struct eia608_screen *get_current_visible_buffer(struct s_write *wb) +{ + struct eia608_screen *data; + if (wb->data608->visible_buffer == 1) + data = &wb->data608->buffer1; + else + data = &wb->data608->buffer2; + return data; +} + +static void swap_visible_buffer(struct s_write *wb) +{ + wb->data608->visible_buffer = (wb->data608->visible_buffer == 1) ? 2 : 1; +} + struct eia608_screen *get_writing_buffer (struct s_write *wb) { struct eia608_screen *use_buffer=NULL; switch (wb->data608->mode) { case MODE_POPUP: // Write on the non-visible buffer - if (wb->data608->visible_buffer==1) - use_buffer = &wb->data608->buffer2; - else - use_buffer = &wb->data608->buffer1; + use_buffer = get_current_hidden_buffer(wb); break; case MODE_ROLLUP_2: // Write directly to screen case MODE_ROLLUP_3: case MODE_ROLLUP_4: - if (wb->data608->visible_buffer==1) - use_buffer = &wb->data608->buffer1; - else - use_buffer = &wb->data608->buffer2; + use_buffer = get_current_visible_buffer(wb); break; default: - fatal (EXIT_BUG_BUG, "Caption mode has an illegal value at get_writing_buffer(), this is a bug.\n"); + fatal (EXIT_BUG_BUG, "Caption mode has an illegal value at get_writing_buffer(), this is a bug.\n"); } return use_buffer; } @@ -1377,7 +1360,7 @@ void write_char (const unsigned char c, struct s_write *wb) wb->data608->cursor_row,wb->data608->cursor_column); */ use_buffer->characters[wb->data608->cursor_row][wb->data608->cursor_column]=c; use_buffer->colors[wb->data608->cursor_row][wb->data608->cursor_column]=wb->data608->color; - use_buffer->fonts[wb->data608->cursor_row][wb->data608->cursor_column]=wb->data608->font; + use_buffer->fonts[wb->data608->cursor_row][wb->data608->cursor_column]=wb->data608->font; use_buffer->row_used[wb->data608->cursor_row]=1; use_buffer->empty=0; if (wb->data608->cursor_column<31) @@ -1427,25 +1410,6 @@ void mstotime (int64_t milli, unsigned *hours, unsigned *minutes, *hours=(int) milli; } -void write_subtitle_file_footer (struct s_write *wb) -{ - switch (write_format) - { - case OF_SAMI: - sprintf ((char *) str,"</BODY></SAMI>\n"); - if (debug_608 && encoding!=ENC_UNICODE) - { - hb_log ("\r%s\n", str); - } - wb->enc_buffer_used=encode_line (wb->enc_buffer,(unsigned char *) str); - //fwrite (enc_buffer,enc_buffer_used,1,wb->fh); - XMLRPC_APPEND(wb->enc_buffer,wb->enc_buffer_used); - break; - default: // Nothing to do. Only SAMI has a footer - break; - } -} - void fhb_log_encoded (FILE *fh, const char *string) { //GUARANTEE(wb, strlen (string)*3); @@ -1453,135 +1417,7 @@ void fhb_log_encoded (FILE *fh, const char *string) //fwrite (wb->enc_buffer,wb->enc_buffer_used,1,fh); } -void write_subtitle_file_header (struct s_write *wb) -{ - switch (write_format) - { - case OF_SRT: // Subrip subtitles have no header - break; - case OF_SAMI: // This header brought to you by McPoodle's CCASDI - //fhb_log_encoded (wb->fh, sami_header); - GUARANTEE(wb, strlen (sami_header)*3); - wb->enc_buffer_used=encode_line (wb->enc_buffer,(unsigned char *) sami_header); - //fwrite (enc_buffer,enc_buffer_used,1,wb->fh); - XMLRPC_APPEND(wb->enc_buffer,wb->enc_buffer_used); - break; - case OF_RCWT: // Write header - //fwrite (rcwt_header, sizeof(rcwt_header),1,wb->fh); - break; - case OF_TRANSCRIPT: // No header. Fall thru - default: - break; - } -} - -void write_cc_line_as_transcript (struct eia608_screen *data, struct s_write *wb, int line_number) -{ - hb_buffer_t *buffer; - - if (sentence_cap) - { - capitalize(line_number,data, &wb->new_sentence); - correct_case(line_number,data); - } - int length = get_decoder_line_basic (wb->subline, line_number, data); - if (debug_608 && encoding!=ENC_UNICODE) - { - hb_log ("\r"); - hb_log ("%s\n",wb->subline); - } - if (length>0) - { - //fwrite (wb->subline, 1, length, wb->fh); - /* - * Put this subtitle in a hb_buffer_t and shove it into the subtitle fifo - */ - buffer = hb_buffer_init( length + 1 ); - buffer->s.frametype = HB_FRAME_SUBTITLE; - buffer->s.start = wb->data608->current_visible_start_ms; - buffer->s.stop = get_fts(wb); - memcpy( buffer->data, wb->subline, length + 1 ); - //hb_log("CC %"PRId64": %s", buffer->s.stop, wb->subline); - - if (wb->hb_last_buffer) { - wb->hb_last_buffer->next = buffer; - } else { - wb->hb_buffer = buffer; - } - wb->hb_last_buffer = buffer; - - XMLRPC_APPEND(wb->subline,length); - //fwrite (encoded_crlf, 1, encoded_crlf_length,wb->fh); - XMLRPC_APPEND(encoded_crlf,encoded_crlf_length); - } - // fhb_log (wb->fh,encoded_crlf); -} - -int write_cc_buffer_as_transcript (struct eia608_screen *data, struct s_write *wb) -{ - int i; - - int wrote_something = 0; - if (debug_608) - { - hb_log ("\n- - - TRANSCRIPT caption - - -\n"); - } - for (i=0;i<15;i++) - { - if (data->row_used[i]) - { - write_cc_line_as_transcript (data,wb, i); - } - wrote_something=1; - } - if (debug_608) - { - hb_log ("- - - - - - - - - - - -\r\n"); - } - return wrote_something; -} - -void write_cc_buffer_to_gui (struct eia608_screen *data, struct s_write *wb) -{ - unsigned h1,m1,s1,ms1; - unsigned h2,m2,s2,ms2; - int i; - - int64_t ms_start= wb->data608->current_visible_start_ms; - - ms_start+=subs_delay; - if (ms_start<0) // Drop screens that because of subs_delay start too early - return; - int time_reported=0; - for (i=0;i<15;i++) - { - if (data->row_used[i]) - { - hb_log ("###SUBTITLE#"); - if (!time_reported) - { - int64_t ms_end = get_fts(wb)+subs_delay; - mstotime (ms_start,&h1,&m1,&s1,&ms1); - mstotime (ms_end-1,&h2,&m2,&s2,&ms2); // -1 To prevent overlapping with next line. - // Note, only MM:SS here as we need to save space in the preview window - hb_log ("%02u:%02u#%02u:%02u#", - h1*60+m1,s1, h2*60+m2,s2); - time_reported=1; - } - else - hb_log ("##"); - - // We don't capitalize here because whatever function that was used - // before to write to file already took care of it. - int length = get_decoder_line_encoded_for_gui (wb->subline, i, data); - fwrite (wb->subline, 1, length, stderr); - fwrite ("\n",1,1,stderr); - } - } - fflush (stderr); -} - -int write_cc_buffer_as_srt (struct eia608_screen *data, struct s_write *wb) +int write_cc_buffer_as_srt(struct eia608_screen *data, struct s_write *wb) { unsigned h1,m1,s1,ms1; unsigned h2,m2,s2,ms2; @@ -1593,36 +1429,30 @@ int write_cc_buffer_as_srt (struct eia608_screen *data, struct s_write *wb) if (ms_start<0) // Drop screens that because of subs_delay start too early return 0; - int64_t ms_end = get_fts(wb)+subs_delay; + int64_t ms_end = get_fts(wb)+subs_delay; mstotime (ms_start,&h1,&m1,&s1,&ms1); mstotime (ms_end-1,&h2,&m2,&s2,&ms2); // -1 To prevent overlapping with next line. - char timeline[128]; + char timeline[128]; wb->data608->srt_counter++; sprintf (timeline,"%u\r\n",wb->data608->srt_counter); - //wb->enc_buffer_used=encode_line (wb->enc_buffer,(unsigned char *) timeline); - //fwrite (wb->enc_buffer,wb->enc_buffer_used,1,wb->fh); - XMLRPC_APPEND(wb->enc_buffer,wb->enc_buffer_used); - //sprintf (timeline, "%02u:%02u:%02u,%03u --> %02u:%02u:%02u,%03u\r\n", - // h1,m1,s1,ms1, h2,m2,s2,ms2); - //wb->enc_buffer_used=encode_line (wb->enc_buffer,(unsigned char *) timeline); + if (debug_608) { hb_log ("\n- - - SRT caption - - -\n"); hb_log ("%s", timeline); } - //fwrite (enc_buffer,enc_buffer_used,1,wb->fh); - XMLRPC_APPEND(wb->enc_buffer,wb->enc_buffer_used); - + /* * Write all the lines into enc_buffer, and then write that out at the end * ensure that we only have two lines, insert a newline after the first one, * and have a big bottom line (strip spaces from any joined lines). */ + wb->enc_buffer_used = 0; int line = 1; for (i=0;i<15;i++) { if (data->row_used[i]) - { + { if (sentence_cap) { capitalize(i,data, &wb->new_sentence); @@ -1633,18 +1463,18 @@ int write_cc_buffer_as_srt (struct eia608_screen *data, struct s_write *wb) * here just in case.. */ if (line == 1) { - wb->enc_buffer_used = get_decoder_line_encoded (wb->enc_buffer, i, data); + wb->enc_buffer_used = get_decoder_line_encoded(wb->enc_buffer, i, data); line = 2; } else { if (line == 2) { - wb->enc_buffer_used += encode_line (wb->enc_buffer+wb->enc_buffer_used, - (unsigned char *) "\n"); + wb->enc_buffer_used += encode_line(wb->enc_buffer+wb->enc_buffer_used, + (unsigned char *) "\n"); line = 3; } else { - wb->enc_buffer_used += encode_line (wb->enc_buffer+wb->enc_buffer_used, - (unsigned char *) " "); + wb->enc_buffer_used += encode_line(wb->enc_buffer+wb->enc_buffer_used, + (unsigned char *) " "); } - wb->enc_buffer_used += get_decoder_line_encoded (wb->enc_buffer+wb->enc_buffer_used, i, data); + wb->enc_buffer_used += get_decoder_line_encoded(wb->enc_buffer+wb->enc_buffer_used, i, data); } } } @@ -1661,126 +1491,40 @@ int write_cc_buffer_as_srt (struct eia608_screen *data, struct s_write *wb) wb->hb_buffer = buffer; } wb->hb_last_buffer = buffer; - - wrote_something=1; - } - if (debug_608) - { - hb_log ("- - - - - - - - - - - -\r\n"); - } - // fhb_log (wb->fh, encoded_crlf); - //fwrite (encoded_crlf, 1, encoded_crlf_length,wb->fh); - XMLRPC_APPEND(encoded_crlf,encoded_crlf_length); - return wrote_something; -} -int write_cc_buffer_as_sami (struct eia608_screen *data, struct s_write *wb) -{ - int wrote_something=0; - int64_t startms = wb->data608->current_visible_start_ms; - int i; - - startms+=subs_delay; - if (startms<0) // Drop screens that because of subs_delay start too early - return 0; - - int64_t endms = get_fts(wb)+subs_delay; - endms--; // To prevent overlapping with next line. - sprintf ((char *) str,"<SYNC start=\"%"PRId64"\"><P class=\"UNKNOWNCC\">\r\n",startms); - if (debug_608 && encoding!=ENC_UNICODE) - { - hb_log ("\r%s\n", str); + wrote_something=1; + wb->clear_sub_needed = 1; } - wb->enc_buffer_used=encode_line (wb->enc_buffer,(unsigned char *) str); - fwrite (wb->enc_buffer,wb->enc_buffer_used,1,wb->fh); - XMLRPC_APPEND(wb->enc_buffer,wb->enc_buffer_used); - for (i=0;i<15;i++) + else if (wb->clear_sub_needed) { - if (data->row_used[i]) - { - int length = get_decoder_line_encoded (wb->subline, i, data); - if (debug_608 && encoding!=ENC_UNICODE) - { - hb_log ("\r"); - hb_log ("%s\n",wb->subline); - } - fwrite (wb->subline, 1, length, wb->fh); - XMLRPC_APPEND(wb->subline,length); - wrote_something=1; - if (i!=14) - { - fwrite (encoded_br, 1, encoded_br_length,wb->fh); - XMLRPC_APPEND(encoded_br, encoded_br_length); - } - fwrite (encoded_crlf, 1, encoded_crlf_length,wb->fh); - XMLRPC_APPEND(encoded_crlf, encoded_crlf_length); + hb_buffer_t *buffer = hb_buffer_init( 1 ); + buffer->s.frametype = HB_FRAME_SUBTITLE; + buffer->s.start = ms_start; + buffer->s.stop = ms_start; + buffer->data[0] = 0; + if (wb->hb_last_buffer != NULL) { + wb->hb_last_buffer->next = buffer; + } else { + wb->hb_buffer = buffer; } + wb->hb_last_buffer = buffer; + wb->clear_sub_needed = 0; } - sprintf ((char *) str,"</P></SYNC>\r\n"); - if (debug_608 && encoding!=ENC_UNICODE) - { - hb_log ("\r%s\n", str); - } - wb->enc_buffer_used=encode_line (wb->enc_buffer,(unsigned char *) str); - fwrite (wb->enc_buffer,wb->enc_buffer_used,1,wb->fh); - XMLRPC_APPEND(wb->enc_buffer,wb->enc_buffer_used); - sprintf ((char *) str,"<SYNC start=\"%"PRId64"\"><P class=\"UNKNOWNCC\"> </P></SYNC>\r\n\r\n",endms); - if (debug_608 && encoding!=ENC_UNICODE) + if (debug_608) { - hb_log ("\r%s\n", str); + hb_log ("- - - - - - - - - - - -\r\n"); } - wb->enc_buffer_used=encode_line (wb->enc_buffer,(unsigned char *) str); - fwrite (wb->enc_buffer,wb->enc_buffer_used,1,wb->fh); - XMLRPC_APPEND(wb->enc_buffer,wb->enc_buffer_used); return wrote_something; } -struct eia608_screen *get_current_visible_buffer (struct s_write *wb) -{ - struct eia608_screen *data; - if (wb->data608->visible_buffer==1) - data = &wb->data608->buffer1; - else - data = &wb->data608->buffer2; - return data; -} - - -int write_cc_buffer (struct s_write *wb) +int write_cc_buffer(struct s_write *wb) { struct eia608_screen *data; int wrote_something=0; - if (screens_to_process!=-1 && wb->data608->screenfuls_counter>=screens_to_process) - { - // We are done. - processed_enough=1; - return 0; - } - if (wb->data608->visible_buffer==1) - data = &wb->data608->buffer1; - else - data = &wb->data608->buffer2; - if (!data->empty) - { - wb->new_sentence=1; - switch (write_format) - { - case OF_SRT: - wrote_something = write_cc_buffer_as_srt (data, wb); - break; - case OF_SAMI: - wrote_something = write_cc_buffer_as_sami (data,wb); - break; - case OF_TRANSCRIPT: - wrote_something = write_cc_buffer_as_transcript (data,wb); - break; - default: - break; - } - if (wrote_something && gui_mode_reports) - write_cc_buffer_to_gui (data,wb); - } + data = get_current_visible_buffer(wb); + wb->new_sentence=1; + wrote_something = write_cc_buffer_as_srt (data, wb); return wrote_something; } @@ -1789,10 +1533,7 @@ void roll_up(struct s_write *wb) struct eia608_screen *use_buffer; int i, j; - if (wb->data608->visible_buffer==1) - use_buffer = &wb->data608->buffer1; - else - use_buffer = &wb->data608->buffer2; + use_buffer = get_current_visible_buffer(wb); int keep_lines; switch (wb->data608->mode) { @@ -1822,7 +1563,7 @@ void roll_up(struct s_write *wb) lastrow=i; } } - + if (debug_608) hb_log ("\rIn roll-up: %d lines used, first: %d, last: %d\n", rows_now, firstrow, lastrow); @@ -1841,7 +1582,7 @@ void roll_up(struct s_write *wb) } for (j=0;j<(1+wb->data608->cursor_row-keep_lines);j++) { - memset(use_buffer->characters[j],' ',CC608_SCREEN_WIDTH); + memset(use_buffer->characters[j],' ',CC608_SCREEN_WIDTH); memset(use_buffer->colors[j],COL_WHITE,CC608_SCREEN_WIDTH); memset(use_buffer->fonts[j],FONT_REGULAR,CC608_SCREEN_WIDTH); use_buffer->characters[j][CC608_SCREEN_WIDTH]=0; @@ -1853,7 +1594,7 @@ void roll_up(struct s_write *wb) use_buffer->characters[lastrow][CC608_SCREEN_WIDTH]=0; use_buffer->row_used[lastrow]=0; - + // Sanity check rows_now=0; for (i=0;i<15;i++) @@ -1869,17 +1610,11 @@ void erase_memory (struct s_write *wb, int displayed) struct eia608_screen *buf; if (displayed) { - if (wb->data608->visible_buffer==1) - buf=&wb->data608->buffer1; - else - buf=&wb->data608->buffer2; + buf = get_current_visible_buffer(wb); } else { - if (wb->data608->visible_buffer==1) - buf=&wb->data608->buffer2; - else - buf=&wb->data608->buffer1; + buf = get_current_hidden_buffer(wb); } clear_eia608_cc_buffer (buf); } @@ -1889,10 +1624,7 @@ int is_current_row_empty (struct s_write *wb) struct eia608_screen *use_buffer; int i; - if (wb->data608->visible_buffer==1) - use_buffer = &wb->data608->buffer1; - else - use_buffer = &wb->data608->buffer2; + use_buffer = get_current_visible_buffer(wb); for (i=0;i<CC608_SCREEN_WIDTH;i++) { if (use_buffer->characters[wb->data608->rollup_base_row][i]!=' ') @@ -1967,23 +1699,27 @@ void handle_command (/*const */ unsigned char c1, const unsigned char c2, struct break; case COM_RESUMECAPTIONLOADING: wb->data608->mode=MODE_POPUP; + wb->data608->current_visible_start_ms = get_fts(wb); break; case COM_RESUMETEXTDISPLAY: wb->data608->mode=MODE_TEXT; + wb->data608->current_visible_start_ms = get_fts(wb); break; - case COM_ROLLUP2: + case COM_ROLLUP2: if (wb->data608->mode==MODE_POPUP) { - if (write_cc_buffer (wb)) + swap_visible_buffer(wb); + if (write_cc_buffer(wb)) wb->data608->screenfuls_counter++; - erase_memory (wb, 1); + erase_memory (wb, 1); } + wb->data608->current_visible_start_ms = get_fts(wb); if (wb->data608->mode==MODE_ROLLUP_2 && !is_current_row_empty(wb)) { if (debug_608) hb_log ("Two RU2, current line not empty. Simulating a CR\n"); handle_command(0x14, 0x2D, wb); - } + } wb->data608->mode=MODE_ROLLUP_2; erase_memory (wb, 0); wb->data608->cursor_column=0; @@ -1992,10 +1728,11 @@ void handle_command (/*const */ unsigned char c1, const unsigned char c2, struct case COM_ROLLUP3: if (wb->data608->mode==MODE_POPUP) { - if (write_cc_buffer (wb)) + if (write_cc_buffer(wb)) wb->data608->screenfuls_counter++; erase_memory (wb, 1); } + wb->data608->current_visible_start_ms = get_fts(wb); if (wb->data608->mode==MODE_ROLLUP_3 && !is_current_row_empty(wb)) { if (debug_608) @@ -2010,17 +1747,18 @@ void handle_command (/*const */ unsigned char c1, const unsigned char c2, struct case COM_ROLLUP4: if (wb->data608->mode==MODE_POPUP) { - if (write_cc_buffer (wb)) + if (write_cc_buffer(wb)) wb->data608->screenfuls_counter++; - erase_memory (wb, 1); + erase_memory (wb, 1); } + wb->data608->current_visible_start_ms = get_fts(wb); if (wb->data608->mode==MODE_ROLLUP_4 && !is_current_row_empty(wb)) { if (debug_608) hb_log ("Two RU4, current line not empty. Simulating a CR\n"); handle_command(0x14, 0x2D, wb); } - + wb->data608->mode=MODE_ROLLUP_4; wb->data608->cursor_column=0; wb->data608->cursor_row=wb->data608->rollup_base_row; @@ -2029,19 +1767,11 @@ void handle_command (/*const */ unsigned char c1, const unsigned char c2, struct case COM_CARRIAGERETURN: // In transcript mode, CR doesn't write the whole screen, to avoid // repeated lines. - if (write_format==OF_TRANSCRIPT) - { - write_cc_line_as_transcript(get_current_visible_buffer (wb), wb, wb->data608->cursor_row); - } - else - { - if (norollup) - delete_all_lines_but_current (get_current_visible_buffer (wb), wb->data608->cursor_row); - if (write_cc_buffer(wb)) - wb->data608->screenfuls_counter++; - } - roll_up(wb); - wb->data608->current_visible_start_ms=get_fts(wb); + if (norollup) + delete_all_lines_but_current(get_current_visible_buffer(wb), wb->data608->cursor_row); + if (write_cc_buffer(wb)) + wb->data608->screenfuls_counter++; + roll_up(wb); wb->data608->cursor_column=0; break; case COM_ERASENONDISPLAYEDMEMORY: @@ -2050,30 +1780,30 @@ void handle_command (/*const */ unsigned char c1, const unsigned char c2, struct case COM_ERASEDISPLAYEDMEMORY: // Write it to disk before doing this, and make a note of the new // time it became clear. - if (write_format==OF_TRANSCRIPT && - (wb->data608->mode==MODE_ROLLUP_2 || wb->data608->mode==MODE_ROLLUP_3 || - wb->data608->mode==MODE_ROLLUP_4)) - { - // In transcript mode we just write the cursor line. The previous lines - // should have been written already, so writing everything produces - // duplicate lines. - write_cc_line_as_transcript(get_current_visible_buffer (wb), wb, wb->data608->cursor_row); - } - else - { - if (write_cc_buffer (wb)) - wb->data608->screenfuls_counter++; - } erase_memory (wb,1); - wb->data608->current_visible_start_ms=get_fts(wb); + // Write "clear" subtitle if necessary + write_cc_buffer(wb); break; case COM_ENDOFCAPTION: // Switch buffers // The currently *visible* buffer is leaving, so now we know it's ending // time. Time to actually write it to file. - if (write_cc_buffer (wb)) + if (wb->data608->mode == MODE_POPUP) + { + swap_visible_buffer(wb); + wb->data608->current_visible_start_ms = get_fts(wb); + } + if (write_cc_buffer(wb)) wb->data608->screenfuls_counter++; - wb->data608->visible_buffer = (wb->data608->visible_buffer==1) ? 2 : 1; - wb->data608->current_visible_start_ms=get_fts(wb); + + if (wb->data608->mode != MODE_POPUP) + swap_visible_buffer(wb); + else if (wb->hb_last_buffer != NULL) + { + // POPUPs are displayed when ENDOFCAPTION is received. + // We do not know their stop time. That is determined by + // ERASEDISPLAYEDMEMORY + wb->hb_last_buffer->s.stop = AV_NOPTS_VALUE; + } wb->data608->cursor_column=0; wb->data608->cursor_row=0; wb->data608->color=default_color; @@ -2089,9 +1819,9 @@ void handle_command (/*const */ unsigned char c1, const unsigned char c2, struct } void handle_end_of_data (struct s_write *wb) -{ +{ // We issue a EraseDisplayedMemory here so if there's any captions pending - // they get written to file. + // they get written to file. handle_command (0x14, 0x2c, wb); // EDM } @@ -2113,7 +1843,7 @@ void handle_double (const unsigned char c1, const unsigned char c2, struct s_wri unsigned char handle_extended (unsigned char hi, unsigned char lo, struct s_write *wb) { // Handle channel change - if (wb->new_channel > 2) + if (wb->new_channel > 2) { wb->new_channel -= 2; if (debug_608) @@ -2139,11 +1869,11 @@ unsigned char handle_extended (unsigned char hi, unsigned char lo, struct s_writ c=lo+0x90; // So if c>=0xb0 && c<=0xcf it comes from here break; } - // This column change is because extended characters replace + // This column change is because extended characters replace // the previous character (which is sent for basic decoders // to show something similar to the real char) - if (wb->data608->cursor_column>0) - wb->data608->cursor_column--; + if (wb->data608->cursor_column>0) + wb->data608->cursor_column--; write_char (c,wb); } @@ -2154,7 +1884,7 @@ unsigned char handle_extended (unsigned char hi, unsigned char lo, struct s_writ void handle_pac (unsigned char c1, unsigned char c2, struct s_write *wb) { // Handle channel change - if (wb->new_channel > 2) + if (wb->new_channel > 2) { wb->new_channel -= 2; if (debug_608) @@ -2199,12 +1929,12 @@ void handle_pac (unsigned char c1, unsigned char c2, struct s_write *wb) wb->data608->cursor_row=row-1 ; // Since the array is 0 based } wb->data608->rollup_base_row=row-1; - wb->data608->cursor_column=indent; + wb->data608->cursor_column=indent; } void handle_single (const unsigned char c1, struct s_write *wb) -{ +{ if (c1<0x20 || wb->data608->channel!=cc_channel) return; // We don't allow special stuff here if (debug_608) @@ -2217,25 +1947,25 @@ void handle_single (const unsigned char c1, struct s_write *wb) int check_channel (unsigned char c1, struct s_write *wb) { - if (c1==0x14) + if (c1==0x14) { if (debug_608 && wb->data608->channel!=1) hb_log ("\nChannel change, now 1\n"); return 1; } - if (c1==0x1c) + if (c1==0x1c) { if (debug_608 && wb->data608->channel!=2) hb_log ("\nChannel change, now 2\n"); return 2; } - if (c1==0x15) + if (c1==0x15) { if (debug_608 && wb->data608->channel!=3) hb_log ("\nChannel change, now 3\n"); return 3; } - if (c1==0x1d) + if (c1==0x1d) { if (debug_608 && wb->data608->channel!=4) hb_log ("\nChannel change, now 4\n"); @@ -2325,14 +2055,12 @@ void process608 (const unsigned char *data, int length, struct s_write *wb) for (i=0;i<length;i=i+2) { unsigned char hi, lo; - int wrote_to_screen=0; + int wrote_to_screen=0; hi = data[i] & 0x7F; // Get rid of parity bit lo = data[i+1] & 0x7F; // Get rid of parity bit if (hi==0 && lo==0) // Just padding continue; - // hb_log ("\r[%02X:%02X]\n",hi,lo); - if (hi>=0x01 && hi<=0x0E) { // XDS crap - mode. Would be nice to support it eventually @@ -2401,8 +2129,8 @@ void process608 (const unsigned char *data, int length, struct s_write *wb) wb->data608->mode==MODE_ROLLUP_4)) { // We don't increase screenfuls_counter here. - write_cc_buffer (wb); - wb->data608->current_visible_start_ms=get_fts(wb); + write_cc_buffer(wb); + wb->data608->current_visible_start_ms = get_fts(wb); } } } @@ -2474,6 +2202,7 @@ int decccInit( hb_work_object_t * w, hb_job_t * job ) { retval = 1; } + init_eia608(pv->cc608->data608); } } } @@ -2507,17 +2236,17 @@ int decccWork( hb_work_object_t * w, hb_buffer_t ** buf_in, } pv->cc608->last_pts = in->s.start; - process608(in->data, in->size, pv->cc608); /* * If there is one waiting then pass it on */ *buf_out = pv->cc608->hb_buffer; + pv->cc608->hb_buffer = NULL; pv->cc608->hb_last_buffer = NULL; - return HB_WORK_OK; + return HB_WORK_OK; } void decccClose( hb_work_object_t * w ) diff --git a/libhb/deccc608sub.h b/libhb/deccc608sub.h index c142c2aec..b281bedbd 100644 --- a/libhb/deccc608sub.h +++ b/libhb/deccc608sub.h @@ -94,6 +94,9 @@ struct s_write { unsigned char *enc_buffer; // Generic general purpose buffer unsigned enc_buffer_used; unsigned enc_buffer_capacity; + + int clear_sub_needed; // Indicates that we need to send a null + // subtitle to clear the current subtitle }; enum command_code diff --git a/libhb/rendersub.c b/libhb/rendersub.c index 403131453..680b5f9ed 100644 --- a/libhb/rendersub.c +++ b/libhb/rendersub.c @@ -6,9 +6,10 @@ It may be used under the terms of the GNU General Public License v2. For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html */ - + #include "hb.h" #include "hbffmpeg.h" +#include "colormap.h" #include <ass/ass.h> struct hb_filter_private_s @@ -24,8 +25,15 @@ struct hb_filter_private_s ASS_Library * ssa; ASS_Renderer * renderer; ASS_Track * ssaTrack; + + // SRT + int line; + hb_buffer_t * current_sub; }; +static char* srt_markup_to_ssa(char *srt, int *len); +static void srt_to_ssa(hb_buffer_t *srt_sub); + // VOBSUB static int vobsub_init( hb_filter_object_t * filter, hb_filter_init_t * init ); @@ -46,6 +54,16 @@ static int ssa_work( hb_filter_object_t * filter, static void ssa_close( hb_filter_object_t * filter ); +// SRT +static int textsub_init( hb_filter_object_t * filter, hb_filter_init_t * init ); + +static int textsub_work( hb_filter_object_t * filter, + hb_buffer_t ** buf_in, + hb_buffer_t ** buf_out ); + +static void textsub_close( hb_filter_object_t * filter ); + + // PGS static int pgssub_init ( hb_filter_object_t * filter, hb_filter_init_t * init ); @@ -119,7 +137,7 @@ static void blend( hb_buffer_t *dst, hb_buffer_t *src, int left, int top ) /* * Merge the luminance and alpha with the picture */ - y_out[left + xx] = + y_out[left + xx] = ( (uint16_t)y_out[left + xx] * ( 255 - alpha ) + (uint16_t)y_in[xx] * alpha ) >> 8; } @@ -335,7 +353,7 @@ static int vobsub_work( hb_filter_object_t * filter, ApplyVOBSubs( pv, in ); *buf_in = NULL; *buf_out = in; - + return HB_FILTER_OK; } @@ -361,7 +379,7 @@ static hb_buffer_t * RenderSSAFrame( hb_filter_private_t * pv, ASS_Image * frame unsigned b = ( frame->color >> 8 ) & 0xff; int yuv = hb_rgb2yuv((r << 16) | (g << 8) | b ); - + unsigned frameY = (yuv >> 16) & 0xff; unsigned frameV = (yuv >> 8 ) & 0xff; unsigned frameU = (yuv >> 0 ) & 0xff; @@ -408,6 +426,7 @@ static void ApplySSASubs( hb_filter_private_t * pv, hb_buffer_t * buf ) { ASS_Image *frameList; hb_buffer_t *sub; + frameList = ass_render_frame( pv->renderer, pv->ssaTrack, buf->s.start / 90, NULL ); if ( !frameList ) @@ -442,17 +461,17 @@ static int ssa_init( hb_filter_object_t * filter, hb_error( "decssasub: libass initialization failed\n" ); return 1; } - + // Redirect libass output to hb_log ass_set_message_cb( pv->ssa, ssa_log, NULL ); - + // Load embedded fonts hb_list_t * list_attachment = init->job->list_attachment; int i; for ( i = 0; i < hb_list_count(list_attachment); i++ ) { hb_attachment_t * attachment = hb_list_item( list_attachment, i ); - + if ( attachment->type == FONT_TTF_ATTACH ) { ass_add_font( @@ -462,41 +481,41 @@ static int ssa_init( hb_filter_object_t * filter, attachment->size ); } } - + ass_set_extract_fonts( pv->ssa, 1 ); ass_set_style_overrides( pv->ssa, NULL ); - + pv->renderer = ass_renderer_init( pv->ssa ); if ( !pv->renderer ) { hb_log( "decssasub: renderer initialization failed\n" ); return 1; } - + ass_set_use_margins( pv->renderer, 0 ); ass_set_hinting( pv->renderer, ASS_HINTING_LIGHT ); // VLC 1.0.4 uses this ass_set_font_scale( pv->renderer, 1.0 ); ass_set_line_spacing( pv->renderer, 1.0 ); - + // Setup default font family - // + // // SSA v4.00 requires that "Arial" be the default font const char *font = NULL; const char *family = "Arial"; // NOTE: This can sometimes block for several *seconds*. // It seems that process_fontdata() for some embedded fonts is slow. ass_set_fonts( pv->renderer, font, family, /*haveFontConfig=*/1, NULL, 1 ); - + // Setup track state pv->ssaTrack = ass_new_track( pv->ssa ); if ( !pv->ssaTrack ) { hb_log( "decssasub: ssa track initialization failed\n" ); return 1; } - + // NOTE: The codec extradata is expected to be in MKV format ass_process_codec_private( pv->ssaTrack, (char *)filter->subtitle->extradata, filter->subtitle->extradata_size ); - + int width = init->width - ( pv->crop[2] + pv->crop[3] ); int height = init->height - ( pv->crop[0] + pv->crop[1] ); ass_set_frame_size( pv->renderer, width, height); @@ -552,12 +571,144 @@ static int ssa_work( hb_filter_object_t * filter, ass_process_chunk( pv->ssaTrack, (char*)sub->data, sub->size, sub->s.start / 90, (sub->s.stop - sub->s.start) / 90 ); + hb_buffer_close(&sub); } ApplySSASubs( pv, in ); *buf_in = NULL; *buf_out = in; - + + return HB_FILTER_OK; +} + +static int textsub_init( hb_filter_object_t * filter, + hb_filter_init_t * init ) +{ + const char * ssa_header = + "[Script Info]\r\n" + "ScriptType: v4.00+\r\n" + "Collisions: Normal\r\n" + "PlayResX: 1920\r\n" + "PlayResY: 1080\r\n" + "Timer: 100.0\r\n" + "WrapStyle: 0\r\n" + "\r\n" + "[V4+ Styles]\r\n" + "Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\r\n" + "Style: Default,Arial,72,&H00FFFFFF,&H00FFFFFF,&H000F0F0F,&H000F0F0F,0,0,0,0,100,100,0,0.00,1,2,3,2,20,20,20,0\r\n"; + + filter->subtitle->extradata = (uint8_t*)ssa_header; + filter->subtitle->extradata_size = strlen(ssa_header); + + int result = ssa_init(filter, init); + + filter->subtitle->extradata = NULL; + filter->subtitle->extradata_size = 0; + + return result; +} + +static void textsub_close( hb_filter_object_t * filter ) +{ + return ssa_close(filter); +} + +static void process_sub(hb_filter_private_t *pv, hb_buffer_t *sub) +{ + char *ssa; + int len; + int64_t start, duration; + + // Create SSA entry + ssa = hb_strdup_printf("%d,,Default,,0,0,0,,%s", ++pv->line, sub->data); + len = strlen(ssa); + + // Parse MKV-SSA packet + // SSA subtitles always have an explicit stop time, so we + // do not need to do special processing for stop == AV_NOPTS_VALUE + start = sub->s.start / 90; + duration = (sub->s.stop - sub->s.start) / 90; + ass_process_chunk( pv->ssaTrack, ssa, len, start, duration); + free(ssa); +} + +static int textsub_work(hb_filter_object_t * filter, + hb_buffer_t ** buf_in, + hb_buffer_t ** buf_out) +{ + hb_filter_private_t * pv = filter->private_data; + hb_buffer_t * in = *buf_in; + hb_buffer_t * sub; + + if (in->size <= 0) + { + *buf_in = NULL; + *buf_out = in; + return HB_FILTER_DONE; + } + + // Get any pending subtitles and add them to the active + // subtitle list + while ((sub = hb_fifo_get(filter->subtitle->fifo_out))) + { + switch (pv->type) + { + case SRTSUB: + case UTF8SUB: + case TX3GSUB: + srt_to_ssa(sub); + break; + default: + break; + } + // Subtitle formats such as CC can have stop times + // that are not known until an "erase display" command + // is encountered in the stream. For these formats + // current_sub is the currently active subtitle for which + // we do not yet know the stop time. We do not currently + // support overlapping subtitles of this type. + if (pv->current_sub != NULL) + { + // Next sub start time tells us the stop time of the + // current sub when it is not known in advance. + pv->current_sub->s.stop = sub->s.start; + process_sub(pv, pv->current_sub); + hb_buffer_close(&pv->current_sub); + } + if (sub->s.start == sub->s.stop) + { + // Zero duration sub used to "clear" previous sub that had + // an unknown duration + hb_buffer_close(&sub); + } + else if (sub->s.stop == AV_NOPTS_VALUE) + { + // We don't know the duration of this sub. So we will + // apply it to every video frame until we see a "clear" sub. + pv->current_sub = sub; + } + else + { + // Duration of this subtitle is known, so we can just + // process it normally. + process_sub(pv, sub); + hb_buffer_close(&sub); + } + } + if (pv->current_sub != NULL && pv->current_sub->s.start < in->s.start) + { + // We don't know the duration of this subtitle, but we know + // that it started before the current video frame and that + // it is still active. So render it on this video frame. + pv->current_sub->s.start = in->s.start; + pv->current_sub->s.stop = in->s.start + 90; + process_sub(pv, pv->current_sub); + } + + ApplySSASubs(pv, in); + *buf_in = NULL; + *buf_out = in; + return HB_FILTER_OK; } @@ -715,6 +866,14 @@ static int hb_rendersub_init( hb_filter_object_t * filter, return ssa_init( filter, init ); } break; + case SRTSUB: + case CC608SUB: + case UTF8SUB: + case TX3GSUB: + { + return textsub_init( filter, init ); + } break; + case PGSSUB: { return pgssub_init( filter, init ); @@ -745,6 +904,14 @@ static int hb_rendersub_work( hb_filter_object_t * filter, return ssa_work( filter, buf_in, buf_out ); } break; + case SRTSUB: + case CC608SUB: + case UTF8SUB: + case TX3GSUB: + { + return textsub_work( filter, buf_in, buf_out ); + } break; + case PGSSUB: { return pgssub_work( filter, buf_in, buf_out ); @@ -773,6 +940,14 @@ static void hb_rendersub_close( hb_filter_object_t * filter ) ssa_close( filter ); } break; + case SRTSUB: + case CC608SUB: + case UTF8SUB: + case TX3GSUB: + { + textsub_close( filter ); + } break; + case PGSSUB: { pgssub_close( filter ); @@ -785,3 +960,113 @@ static void hb_rendersub_close( hb_filter_object_t * filter ) } } +static char* srt_markup_to_ssa(char *srt, int *len) +{ + char terminator; + char color[40]; + uint32_t rgb; + + *len = 0; + if (srt[0] != '<' && srt[0] != '{') + return NULL; + + if (srt[0] == '<') + terminator = '>'; + else + terminator = '}'; + + if (srt[1] == 'i' && srt[2] == terminator) + { + *len = 3; + return hb_strdup_printf("{\\i1}"); + } + else if (srt[1] == 'b' && srt[2] == terminator) + { + *len = 3; + return hb_strdup_printf("{\\b1}"); + } + else if (srt[1] == 'u' && srt[2] == terminator) + { + *len = 3; + return hb_strdup_printf("{\\u1}"); + } + else if (srt[1] == '/' && srt[2] == 'i' && srt[3] == terminator) + { + *len = 4; + return hb_strdup_printf("{\\i0}"); + } + else if (srt[1] == '/' && srt[2] == 'b' && srt[3] == terminator) + { + *len = 4; + return hb_strdup_printf("{\\b0}"); + } + else if (srt[1] == '/' && srt[2] == 'u' && srt[3] == terminator) + { + *len = 4; + return hb_strdup_printf("{\\u0}"); + } + else if (srt[0] == '<' && !strncmp(srt + 1, "font", 4)) + { + int match; + match = sscanf(srt + 1, "font color=\"%39[^\"]\">", color); + if (match != 1) + { + return NULL; + } + while (srt[*len] != '>') (*len)++; + (*len)++; + if (color[0] == '#') + rgb = strtol(color + 1, NULL, 16); + else + rgb = hb_rgb_lookup_by_name(color); + return hb_strdup_printf("{\\1c&H%X&}", HB_RGB_TO_BGR(rgb)); + } + else if (srt[0] == '<' && srt[1] == '/' && !strncmp(srt + 2, "font", 4) && + srt[6] == '>') + { + *len = 7; + return hb_strdup_printf("{\\1c&HFFFFFF&}"); + } + + return NULL; +} + +static void srt_to_ssa(hb_buffer_t *sub_in) +{ + char * srt = (char*)sub_in->data; + // SSA markup expands a little over SRT, so allocate a bit of extra + // space. More will be realloc'd if needed. + hb_buffer_t * sub = hb_buffer_init(sub_in->size + 20); + char * ssa, *ssa_markup; + int skip, len, pos, ii; + + // Exchange data between input sub and new ssa_sub + // After this, sub_in contains ssa data + hb_buffer_swap_copy(sub_in, sub); + pos = 0; + ii = 0; + while (srt[ii] != '\0') + { + if ((ssa_markup = srt_markup_to_ssa(srt + ii, &skip)) != NULL) + { + len = strlen(ssa_markup); + hb_buffer_realloc(sub_in, pos + len + 1); + // After realloc, sub_in->data may change + ssa = (char*)sub_in->data; + snprintf(ssa + pos, len + 1, "%s", ssa_markup); + free(ssa_markup); + pos += len; + ii += skip; + } + else + { + hb_buffer_realloc(sub_in, pos + 2); + // After realloc, sub_in->data may change + ssa = (char*)sub_in->data; + ssa[pos++] = srt[ii++]; + } + } + ssa[pos] = '\0'; + hb_buffer_close(&sub); +} + diff --git a/libhb/stream.c b/libhb/stream.c index a48d339f1..b133dda78 100644 --- a/libhb/stream.c +++ b/libhb/stream.c @@ -5228,9 +5228,12 @@ static void add_ffmpeg_subtitle( hb_title_t *title, hb_stream_t *stream, int id strncpy( subtitle->iso639_2, language->iso639_2, 4 ); // Copy the extradata for the subtitle track - subtitle->extradata = malloc( codec->extradata_size ); - memcpy( subtitle->extradata, codec->extradata, codec->extradata_size ); - subtitle->extradata_size = codec->extradata_size; + if (codec->extradata != NULL) + { + subtitle->extradata = malloc( codec->extradata_size ); + memcpy( subtitle->extradata, codec->extradata, codec->extradata_size ); + subtitle->extradata_size = codec->extradata_size; + } subtitle->track = id; hb_list_add(title->list_subtitle, subtitle); diff --git a/libhb/sync.c b/libhb/sync.c index 80ee15836..84eb1eac5 100644 --- a/libhb/sync.c +++ b/libhb/sync.c @@ -427,14 +427,23 @@ static hb_buffer_t * sanitizeSubtitle( sanitizer->last->s.stop = sub->s.start; } - if (sanitizer->last == NULL) + if (sub->s.start == sub->s.stop) { - sanitizer->list_current = sanitizer->last = sub; + // Used to indicate "clear" subtitles when the duration + // of subtitles is not encoded in the stream + hb_buffer_close(&sub); } - else + if (sub != NULL) { - sanitizer->last->next = sub; - sanitizer->last = sub; + if (sanitizer->last == NULL) + { + sanitizer->list_current = sanitizer->last = sub; + } + else + { + sanitizer->last->next = sub; + sanitizer->last = sub; + } } return mergeSubtitles(sanitizer, 0); } diff --git a/libhb/work.c b/libhb/work.c index d0a0f6cd3..92e8692d0 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -413,8 +413,9 @@ void hb_display_job_info(hb_job_t *job) else if( subtitle->source == SRTSUB ) { /* For SRT, print offset and charset too */ - hb_log( " * subtitle track %d, %s (track %d, id 0x%x) Text [SRT] -> Passthrough%s, offset: %"PRId64", charset: %s", + hb_log( " * subtitle track %d, %s (track %d, id 0x%x) Text [SRT] -> %s%s, offset: %"PRId64", charset: %s", subtitle->out_track, subtitle->lang, subtitle->track, subtitle->id, + subtitle->config.dest == RENDERSUB ? "Render/Burn-in" : "Passthrough", subtitle->config.default_track ? ", Default" : "", subtitle->config.offset, subtitle->config.src_codeset ); } diff --git a/macosx/Controller.m b/macosx/Controller.m index bc63ae217..6432352be 100644 --- a/macosx/Controller.m +++ b/macosx/Controller.m @@ -3584,16 +3584,27 @@ bool one_burned = FALSE; /* we need to srncpy file path and char code */ strncpy(sub_config.src_filename, [[tempObject objectForKey:@"subtitleSourceSrtFilePath"] UTF8String], 255); sub_config.src_filename[255] = 0; - strncpy(sub_config.src_codeset, [[tempObject objectForKey:@"subtitleTrackSrtCharCode"] UTF8String], 39); - sub_config.src_codeset[39] = 0; - - sub_config.force = 0; - sub_config.dest = PASSTHRUSUB; - sub_config.default_track = def; - - hb_srt_add( job, &sub_config, [[tempObject objectForKey:@"subtitleTrackSrtLanguageIso3"] UTF8String]); - continue; - } + strncpy(sub_config.src_codeset, [[tempObject objectForKey:@"subtitleTrackSrtCharCode"] UTF8String], 39);
+ sub_config.src_codeset[39] = 0;
+
+ if( !burned && hb_subtitle_can_pass( SRTSUB, job->mux ) )
+ {
+ sub_config.dest = PASSTHRUSUB;
+ }
+ else if( hb_subtitle_can_burn( SRTSUB ) )
+ {
+ // Only allow one subtitle to be burned into the video
+ if( one_burned )
+ continue;
+ one_burned = TRUE;
+ sub_config.dest = RENDERSUB;
+ }
+
+ sub_config.force = 0;
+ sub_config.default_track = def;
+ hb_srt_add( job, &sub_config, [[tempObject objectForKey:@"subtitleTrackSrtLanguageIso3"] UTF8String]);
+ continue;
+ }
/* for the actual source tracks, we must subtract the non source entries so * that the menu index matches the source subtitle_list index for convenience */ @@ -4144,16 +4155,27 @@ bool one_burned = FALSE; /* we need to srncpy file name and codeset */ strncpy(sub_config.src_filename, [[tempObject objectForKey:@"subtitleSourceSrtFilePath"] UTF8String], 255); sub_config.src_filename[255] = 0; - strncpy(sub_config.src_codeset, [[tempObject objectForKey:@"subtitleTrackSrtCharCode"] UTF8String], 39); - sub_config.src_codeset[39] = 0; - - sub_config.force = 0; - sub_config.dest = PASSTHRUSUB; - sub_config.default_track = def; - - hb_srt_add( job, &sub_config, [[tempObject objectForKey:@"subtitleTrackSrtLanguageIso3"] UTF8String]); - continue; - } + strncpy(sub_config.src_codeset, [[tempObject objectForKey:@"subtitleTrackSrtCharCode"] UTF8String], 39);
+ sub_config.src_codeset[39] = 0;
+
+ if( !burned && hb_subtitle_can_pass( SRTSUB, job->mux ) )
+ {
+ sub_config.dest = PASSTHRUSUB;
+ }
+ else if( hb_subtitle_can_burn( SRTSUB ) )
+ {
+ // Only allow one subtitle to be burned into the video
+ if( one_burned )
+ continue;
+ one_burned = TRUE;
+ sub_config.dest = RENDERSUB;
+ }
+
+ sub_config.force = 0;
+ sub_config.default_track = def;
+ hb_srt_add( job, &sub_config, [[tempObject objectForKey:@"subtitleTrackSrtLanguageIso3"] UTF8String]);
+ continue;
+ }
/* for the actual source tracks, we must subtract the non source entries so * that the menu index matches the source subtitle_list index for convenience */ diff --git a/macosx/HBSubtitles.m b/macosx/HBSubtitles.m index 6760b5d3e..d8474ac09 100644 --- a/macosx/HBSubtitles.m +++ b/macosx/HBSubtitles.m @@ -96,20 +96,17 @@ hb_subtitle_t *subtitle; NSMutableArray *forcedSourceNamesArray = [[NSMutableArray alloc] init]; for (i = 0; i < hb_list_count(fTitle->list_subtitle); i++) - { - subtitle = (hb_subtitle_t*)hb_list_item(fTitle->list_subtitle, i); - - /* Subtitle source features */ - int canBeBurnedIn = hb_subtitle_can_burn(subtitle->source); - int supportsForcedFlags = hb_subtitle_can_force(subtitle->source); - /* Human-readable representation of subtitle->source */ - NSString *bitmapOrText = subtitle->format == PICTURESUB ? @"Bitmap" : @"Text"; - NSString *subSourceName = [NSString stringWithUTF8String:hb_subsource_name(subtitle->source)]; - /* if the subtitle track can be forced, add its source name to the array */ - if (supportsForcedFlags && - [forcedSourceNamesArray containsObject:subSourceName] == NO) - { - [forcedSourceNamesArray addObject:subSourceName]; + {
+ subtitle = (hb_subtitle_t*)hb_list_item(fTitle->list_subtitle, i);
+
+ /* Human-readable representation of subtitle->source */
+ NSString *bitmapOrText = subtitle->format == PICTURESUB ? @"Bitmap" : @"Text";
+ NSString *subSourceName = [NSString stringWithUTF8String:hb_subsource_name(subtitle->source)];
+ /* if the subtitle track can be forced, add its source name to the array */
+ if (hb_subtitle_can_force(subtitle->source) &&
+ [forcedSourceNamesArray containsObject:subSourceName] == NO)
+ {
+ [forcedSourceNamesArray addObject:subSourceName];
} /* create a dictionary of source subtitle information to store in our array */ @@ -117,16 +114,14 @@ /* Subtitle Source track name */ [newSubtitleSourceTrack setObject:[NSString stringWithFormat:@"%d - %@ - (%@) (%@)", i, [NSString stringWithUTF8String:subtitle->lang], - bitmapOrText,subSourceName] - forKey:@"sourceTrackName"]; - /* Subtitle Source track number, type and features */ - [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:i] forKey:@"sourceTrackNum"]; - [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:subtitle->source] forKey:@"sourceTrackType"]; - [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:canBeBurnedIn] forKey:@"sourceTrackCanBeBurnedIn"]; - [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:supportsForcedFlags] forKey:@"sourceTrackSupportsForcedFlags"]; - [subtitleSourceArray addObject:newSubtitleSourceTrack]; - [newSubtitleSourceTrack autorelease]; - } + bitmapOrText,subSourceName]
+ forKey:@"sourceTrackName"];
+ /* Subtitle Source track number, type and features */
+ [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:i] forKey:@"sourceTrackNum"];
+ [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:subtitle->source] forKey:@"sourceTrackType"];
+ [subtitleSourceArray addObject:newSubtitleSourceTrack];
+ [newSubtitleSourceTrack autorelease];
+ }
/* now set the name of the Foreign Audio Search track */ if ([forcedSourceNamesArray count]) @@ -185,16 +180,12 @@ /* Subtitle track forced state */ [newSubtitleTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackForced"]; /* Subtitle track burned state */ - [newSubtitleTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackBurned"]; - /* Subtitle track default state */ - [newSubtitleTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackDefault"]; - /* Subtitle Source track canBeBurnedIn */ - [newSubtitleTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleSourceTrackCanBeBurnedIn"]; - /* Subtitle Source track supportsForcedFlags */ - [newSubtitleTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleSourceTrackSupportsForcedFlags"]; - - [newSubtitleTrack autorelease]; - return newSubtitleTrack; + [newSubtitleTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackBurned"];
+ /* Subtitle track default state */
+ [newSubtitleTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackDefault"];
+
+ [newSubtitleTrack autorelease];
+ return newSubtitleTrack;
} - (void)createSubtitleSrtTrack:(NSURL *)fileURL @@ -209,16 +200,12 @@ [newSubtitleSourceTrack setObject:displayname forKey:@"sourceTrackName"]; /* Subtitle Source track type (VobSub, Srt, etc.) */ [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:SRTSUB] forKey:@"sourceTrackType"]; - [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:SRTSUB] forKey:@"subtitleSourceTrackType"]; - /* Subtitle Source file path */ - [newSubtitleSourceTrack setObject:[fileURL path] forKey:@"sourceSrtFilePath"]; - /* Subtitle Source track canBeBurnedIn */ - [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:0] forKey:@"sourceTrackCanBeBurnedIn"]; - /* Subtitle Source track supportsForcedFlags */ - [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:0] forKey:@"sourceTrackSupportsForcedFlags"]; - - [subtitleSourceArray addObject:newSubtitleSourceTrack]; - [newSubtitleSourceTrack autorelease]; + [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:SRTSUB] forKey:@"subtitleSourceTrackType"];
+ /* Subtitle Source file path */
+ [newSubtitleSourceTrack setObject:[fileURL path] forKey:@"sourceSrtFilePath"];
+
+ [subtitleSourceArray addObject:newSubtitleSourceTrack];
+ [newSubtitleSourceTrack autorelease];
/* Now create a new srt subtitle dictionary assuming the user wants to add it to their list * Note: the subtitle array always has last entry for "None", so we need to replace its @@ -244,16 +231,12 @@ /* Subtitle track forced state */ [newSubtitleSrtTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackForced"]; /* Subtitle track burned state */ - [newSubtitleSrtTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackBurned"]; - /* Subtitle track default state */ - [newSubtitleSrtTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackDefault"]; - /* Subtitle Source track canBeBurnedIn */ - [newSubtitleSrtTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleSourceTrackCanBeBurnedIn"]; - /* Subtitle Source track supportsForcedFlags */ - [newSubtitleSrtTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleSourceTrackSupportsForcedFlags"]; - - /* now the srt only info, Language, Chart Code and offset */ - [newSubtitleSrtTrack setObject:[fileURL path] forKey:@"subtitleSourceSrtFilePath"]; + [newSubtitleSrtTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackBurned"];
+ /* Subtitle track default state */
+ [newSubtitleSrtTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackDefault"];
+
+ /* now the srt only info, Language, Chart Code and offset */
+ [newSubtitleSrtTrack setObject:[fileURL path] forKey:@"subtitleSourceSrtFilePath"];
[newSubtitleSrtTrack setObject:[NSNumber numberWithInteger:languagesArrayDefIndex] forKey:@"subtitleTrackSrtLanguageIndex"]; [newSubtitleSrtTrack setObject:[[languagesArray objectAtIndex:languagesArrayDefIndex] objectAtIndex:0] forKey:@"subtitleTrackSrtLanguageLong"]; [newSubtitleSrtTrack setObject:[[languagesArray objectAtIndex:languagesArrayDefIndex] objectAtIndex:1] forKey:@"subtitleTrackSrtLanguageIso3"]; @@ -311,16 +294,12 @@ [newSubtitleSourceTrack setObject:displayname forKey:@"sourceTrackName"]; /* Subtitle Source track type (VobSub, Srt, etc.) */ [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:SRTSUB] forKey:@"sourceTrackType"]; - [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:SRTSUB] forKey:@"subtitleSourceTrackType"]; - /* Subtitle Source file path */ - [newSubtitleSourceTrack setObject:filePath forKey:@"sourceSrtFilePath"]; - /* Subtitle Source track canBeBurnedIn */ - [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:0] forKey:@"sourceTrackCanBeBurnedIn"]; - /* Subtitle Source track supportsForcedFlags */ - [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:0] forKey:@"sourceTrackSupportsForcedFlags"]; - - [subtitleSourceArray addObject:newSubtitleSourceTrack]; - [newSubtitleSourceTrack autorelease]; + [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:SRTSUB] forKey:@"subtitleSourceTrackType"];
+ /* Subtitle Source file path */
+ [newSubtitleSourceTrack setObject:filePath forKey:@"sourceSrtFilePath"];
+
+ [subtitleSourceArray addObject:newSubtitleSourceTrack];
+ [newSubtitleSourceTrack autorelease];
/* END replicate the add new srt code above */ } i++; @@ -505,14 +484,12 @@ hb_subsource_name(PGSSUB)]].location != NSNotFound) { subtitleTrackType = PGSSUB; - } - // now set the track type - [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:subtitleTrackType] forKey:@"subtitleSourceTrackType"]; - [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:1] forKey:@"subtitleSourceTrackCanBeBurnedIn"]; - [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:1] forKey:@"subtitleSourceTrackSupportsForcedFlags"]; - // foreign lang search is most useful when combined w/Forced Only - make it default - [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:1] forKey:@"subtitleTrackForced"]; - } + }
+ // now set the track type
+ [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:subtitleTrackType] forKey:@"subtitleSourceTrackType"];
+ // foreign lang search is most useful when combined w/Forced Only - make it default
+ [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:1] forKey:@"subtitleTrackForced"];
+ }
/* check to see if we are an srt, in which case set our file path and source track type kvp's*/ else if ([[[subtitleSourceArray objectAtIndex:sourceSubtitleIndex] objectForKey:@"sourceTrackType"] intValue] == SRTSUB) { @@ -522,25 +499,21 @@ forKey:@"subtitleSourceSrtFilePath"]; } else - { - [[subtitleArray objectAtIndex:rowIndex] setObject:[[subtitleSourceArray objectAtIndex:sourceSubtitleIndex] objectForKey:@"sourceTrackType"] - forKey:@"subtitleSourceTrackType"]; - [[subtitleArray objectAtIndex:rowIndex] setObject:[[subtitleSourceArray objectAtIndex:sourceSubtitleIndex] objectForKey:@"sourceTrackCanBeBurnedIn"] - forKey:@"subtitleSourceTrackCanBeBurnedIn"]; - [[subtitleArray objectAtIndex:rowIndex] setObject:[[subtitleSourceArray objectAtIndex:sourceSubtitleIndex] objectForKey:@"sourceTrackSupportsForcedFlags"] - forKey:@"subtitleSourceTrackSupportsForcedFlags"]; - } - - if([[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackCanBeBurnedIn"] intValue] == 0) - { - /* the source track cannot be burned in, so uncheck the widget */ - [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackBurned"]; - } - - if([[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackSupportsForcedFlags"] intValue] == 0) - { - /* the source track does not support forced flags, so uncheck the widget */ - [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackForced"]; + {
+ [[subtitleArray objectAtIndex:rowIndex] setObject:[[subtitleSourceArray objectAtIndex:sourceSubtitleIndex] objectForKey:@"sourceTrackType"]
+ forKey:@"subtitleSourceTrackType"];
+ }
+
+ if (!hb_subtitle_can_burn([[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackType"] intValue]))
+ {
+ /* the source track cannot be burned in, so uncheck the widget */
+ [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackBurned"];
+ }
+
+ if (!hb_subtitle_can_force([[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackType"] intValue]))
+ {
+ /* the source track does not support forced flags, so uncheck the widget */
+ [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackForced"];
} } } @@ -715,13 +688,13 @@ if ([[aTableColumn identifier] isEqualToString:@"forced"]) { - [aCell setState:[[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleTrackForced"] intValue]]; - /* Disable the "Forced Only" checkbox if a) the track is "None" or b) the subtitle track doesn't support forced flags */ - if (![[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackNum"] intValue] || - ![[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackSupportsForcedFlags"] intValue]) - { - [aCell setEnabled:NO]; - } + [aCell setState:[[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleTrackForced"] intValue]];
+ /* Disable the "Forced Only" checkbox if a) the track is "None" or b) the subtitle track doesn't support forced flags */
+ if (![[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackNum"] intValue] ||
+ !hb_subtitle_can_force([[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackType"] intValue]))
+ {
+ [aCell setEnabled:NO];
+ }
else { [aCell setEnabled:YES]; @@ -733,15 +706,15 @@ /* * Disable the "Burned In" checkbox if: * a) the track is "None" OR - * b) the subtitle track can't be burned in OR - * c) the subtitle track can't be passed through (e.g. PGS w/MP4) - */ - if (![[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackNum"] intValue] || - ![[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackCanBeBurnedIn"] intValue] || - !hb_subtitle_can_pass([[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackType"] intValue], container)) - { - [aCell setEnabled:NO]; - } + * b) the subtitle track can't be burned in OR
+ * c) the subtitle track can't be passed through (e.g. PGS w/MP4)
+ */
+ int subtitleTrackType = [[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackType"] intValue];
+ if (![[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackNum"] intValue] ||
+ !hb_subtitle_can_burn(subtitleTrackType) || !hb_subtitle_can_pass(subtitleTrackType, container))
+ {
+ [aCell setEnabled:NO];
+ }
else { [aCell setEnabled:YES]; |