#include <sys/time.h>
#include "common.h"
+#include "lang.h"
#include "hb.h"
/**********************************************************************
/* We fail! */
return 0;
}
- subtitle->config = *subtitlecfg;
+ subtitle->config = *subtitlecfg;
hb_list_add(job->list_subtitle, subtitle);
return 1;
}
+int hb_srt_add( const hb_job_t * job,
+ const hb_subtitle_config_t * subtitlecfg,
+ const char *lang )
+{
+ hb_subtitle_t *subtitle;
+ iso639_lang_t *language = NULL;
+ int retval = 0;
+
+ subtitle = calloc( 1, sizeof( *subtitle ) );
+
+ subtitle->format = TEXTSUB;
+ subtitle->source = SRTSUB;
+
+ language = lang_for_code2( lang );
+
+ if( language )
+ {
+
+ strcpy( subtitle->lang, language->eng_name );
+ strncpy( subtitle->iso639_2, lang, 4 );
+
+ subtitle->config = *subtitlecfg;
+ subtitle->config.dest = PASSTHRUSUB;
+
+ hb_list_add(job->list_subtitle, subtitle);
+ retval = 1;
+ }
+ return retval;
+}
hb_audio_config_t * hb_list_audio_config_item(hb_list_t * list, int i);
int hb_subtitle_add(const hb_job_t * job, const hb_subtitle_config_t * subtitlecfg, int track);
+int hb_srt_add(const hb_job_t * job, const hb_subtitle_config_t * subtitlecfg,
+ const char *lang);
+
struct hb_rate_s
{
{
enum subdest { RENDERSUB, PASSTHRUSUB } dest;
int force;
- int default_track;
+ int default_track;
+ char src_filename[128];
+ char src_codeset[40];
+ int64_t offset;
};
#define HB_VIDEO_RATE_BASE 27000000
extern hb_work_object_t hb_decvobsub;
extern hb_work_object_t hb_encvobsub;
extern hb_work_object_t hb_deccc608;
+extern hb_work_object_t hb_decsrtsub;
extern hb_work_object_t hb_render;
extern hb_work_object_t hb_encavcodec;
extern hb_work_object_t hb_encx264;
hb_register( &hb_decvobsub );
hb_register( &hb_encvobsub );
hb_register( &hb_deccc608 );
+ hb_register( &hb_decsrtsub );
hb_register( &hb_render );
hb_register( &hb_encavcodec );
hb_register( &hb_encx264 );
hb_register( &hb_decvobsub );
hb_register( &hb_encvobsub );
hb_register( &hb_deccc608 );
+ hb_register( &hb_decsrtsub );
hb_register( &hb_render );
hb_register( &hb_encavcodec );
hb_register( &hb_encx264 );
WORK_DECMPEG2,
WORK_DECCC608,
WORK_DECVOBSUB,
+ WORK_DECSRTSUB,
WORK_ENCVOBSUB,
WORK_RENDER,
WORK_ENCAVCODEC,
__deps__ := A52DEC BZIP2 FAAC FAAD2 FFMPEG LAME LIBDCA \
- LIBDVDREAD LIBDVDNAV LIBMKV LIBOGG LIBSAMPLERATE LIBTHEORA LIBVORBIS \
+ LIBDVDREAD LIBDVDNAV LIBICONV LIBMKV LIBOGG LIBSAMPLERATE LIBTHEORA LIBVORBIS \
MP4V2 MPEG2DEC PTHREADW32 X264 ZLIB
$(eval $(call import.MODULE.defs,LIBHB,libhb,$(__deps__)))
LIBHB.lib = $(LIBHB.build/)hb.lib
LIBHB.dll.libs = $(foreach n, \
- a52 bz2 avcodec avformat avutil dca dvdnav dvdread faac faad mkv mpeg2 mp3lame mp4v2 \
+ a52 bz2 avcodec avformat avutil dca dvdnav dvdread faac faad iconv mkv mpeg2 mp3lame mp4v2 \
ogg pthreadGC2 samplerate swscale theora vorbis vorbisenc x264 z, \
$(CONTRIB.build/)lib/lib$(n).a )
* Rewrite timestamps on subtitles that need it (on raw queue).
*/
if( subtitle->source == CC608SUB ||
- subtitle->source == CC708SUB )
+ subtitle->source == CC708SUB ||
+ subtitle->source == SRTSUB )
{
/*
* Rewrite timestamps on subtitles that came from Closed Captions
hb_list_add( job->list_work, w );
}
+ if( !job->indepth_scan && subtitle->source == SRTSUB )
+ {
+ w = hb_get_work( WORK_DECSRTSUB );
+ w->fifo_in = subtitle->fifo_in;
+ w->fifo_out = subtitle->fifo_raw;
+ w->subtitle = subtitle;
+ hb_list_add( job->list_work, w );
+ }
+
if( !job->indepth_scan &&
subtitle->format == PICTURESUB
&& subtitle->config.dest == PASSTHRUSUB )
2713E6300F676510002E0A01 /* libhb.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2713E50C0F675F32002E0A01 /* libhb.a */; };
2713E6420F676526002E0A01 /* libhb.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2713E50C0F675F32002E0A01 /* libhb.a */; };
2728D25B0FE8419900758EC9 /* HandBrake-64.icns in Resources */ = {isa = PBXBuildFile; fileRef = 2728D25A0FE8419900758EC9 /* HandBrake-64.icns */; };
+ 274DD1E40FEF109900881E69 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 274DD1E30FEF109900881E69 /* libiconv.dylib */; };
+ 274DD20B0FEF10FD00881E69 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 274DD1E30FEF109900881E69 /* libiconv.dylib */; };
2774BE900F66F47100B65FC6 /* libbz2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2774BE8F0F66F47100B65FC6 /* libbz2.dylib */; };
2774BE920F66F48200B65FC6 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2774BE910F66F48200B65FC6 /* libz.dylib */; };
2774BEC70F66F61A00B65FC6 /* libbz2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2774BE8F0F66F47100B65FC6 /* libbz2.dylib */; };
25DE1FB50C169A0C00F01FC8 /* HBPreferencesController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBPreferencesController.m; sourceTree = "<group>"; };
2713E50C0F675F32002E0A01 /* libhb.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libhb.a; path = libhb/libhb.a; sourceTree = BUILT_PRODUCTS_DIR; };
2728D25A0FE8419900758EC9 /* HandBrake-64.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = "HandBrake-64.icns"; sourceTree = "<group>"; };
+ 274DD1E30FEF109900881E69 /* libiconv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.dylib; path = /usr/lib/libiconv.dylib; sourceTree = "<absolute>"; };
2774BE8F0F66F47100B65FC6 /* libbz2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libbz2.dylib; path = usr/lib/libbz2.dylib; sourceTree = SDKROOT; };
2774BE910F66F48200B65FC6 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
27AC71840F5A0AF600053B83 /* fakexcode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = fakexcode.cpp; path = ../test/fakexcode.cpp; sourceTree = SOURCE_ROOT; };
buildActionMask = 2147483647;
files = (
D289A9F30DBBE7AC00CE614B /* CoreServices.framework in Frameworks */,
+ A906A0520F7A7B210007A827 /* AudioToolbox.framework in Frameworks */,
D289AAC40DBBF3F100CE614B /* IOKit.framework in Frameworks */,
2713E6300F676510002E0A01 /* libhb.a in Frameworks */,
+ 274DD1E40FEF109900881E69 /* libiconv.dylib in Frameworks */,
2774BE900F66F47100B65FC6 /* libbz2.dylib in Frameworks */,
2774BE920F66F48200B65FC6 /* libz.dylib in Frameworks */,
- A906A0520F7A7B210007A827 /* AudioToolbox.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A25962E10F15077500B3BF4E /* Quartz.framework in Frameworks */,
A20F47010EBB5EC2005B861B /* QTKit.framework in Frameworks */,
4DD93FA4082036E8008E1322 /* OpenGL.framework in Frameworks */,
+ A906A0510F7A7B210007A827 /* AudioToolbox.framework in Frameworks */,
4DD93FA3082036E8008E1322 /* IOKit.framework in Frameworks */,
A29E05800BE1283E000533F5 /* Growl.framework in Frameworks */,
A2D0A0AB0D3E5929002D57CB /* Sparkle.framework in Frameworks */,
2713E6420F676526002E0A01 /* libhb.a in Frameworks */,
+ 274DD20B0FEF10FD00881E69 /* libiconv.dylib in Frameworks */,
2774BEC70F66F61A00B65FC6 /* libbz2.dylib in Frameworks */,
2774BEC80F66F61A00B65FC6 /* libz.dylib in Frameworks */,
- A906A0510F7A7B210007A827 /* AudioToolbox.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
089C165CFE840E0CC02AAC07 /* InfoPlist.strings */,
29B97323FDCFA39411CA2CEA /* Frameworks */,
19C28FACFE9D520D11CA2CBB /* Products */,
+ 274DD1E30FEF109900881E69 /* libiconv.dylib */,
);
name = HandBrake;
sourceTree = "<group>";
MODULES += contrib/x264
ifneq (,$(filter $(BUILD.system),cygwin mingw))
+ MODULES += contrib/libiconv
MODULES += contrib/zlib
endif
TEST.install.exe = $(PREFIX/)bin/$(notdir $(TEST.exe))
+ifeq (1,$(LIBICONV.enabled))
+ TEST.libs += $(CONTRIB.build/)lib/libiconv.a
+endif
ifeq (1,$(BZIP2.enabled))
TEST.libs += $(CONTRIB.build/)lib/libbz2.a
endif
ifeq ($(BUILD.system),darwin)
TEST.GCC.f += IOKit CoreServices AudioToolbox
- TEST.GCC.l += bz2 z
+ TEST.GCC.l += iconv bz2 z
else ifeq ($(BUILD.system),linux)
TEST.GCC.l += bz2 z pthread dl m
else ifeq (1-mingw,$(BUILD.cross)-$(BUILD.system))
static char ** subforce = NULL;
static char * subburn = NULL;
static char * subdefault = NULL;
+static char ** srtfile = NULL;
+static char ** srtcodeset = NULL;
+static char ** srtoffset = NULL;
+static char ** srtlang = NULL;
static int subtitle_scan = 0;
static int width = 0;
static int height = 0;
}
}
+ if( srtfile )
+ {
+ char * token;
+ int i, pos;
+ hb_subtitle_config_t sub_config;
+
+ pos = 0;
+ for( i=0; srtfile[i] != NULL; i++ )
+ {
+ char *codeset = "L1";
+ int64_t offset = 0;
+ char *lang = "und";
+
+ pos++;
+ token = srtfile[i];
+ if( srtcodeset && srtcodeset[i] )
+ {
+ codeset = srtcodeset[i];
+ }
+ if( srtoffset && srtoffset[i] )
+ {
+ offset = strtoll( srtoffset[i], &srtoffset[i], 0 );
+ }
+ if ( srtlang && srtlang[i] )
+ {
+ lang = srtlang[i];
+ }
+ sub_config.force = 0;
+ sub_config.default_track = 0;
+ strncpy( sub_config.src_filename, srtfile[i], 128);
+ strncpy( sub_config.src_codeset, codeset, 40);
+ sub_config.offset = offset;
+
+ hb_srt_add( job, &sub_config, lang);
+ }
+ }
+
if( native_language )
{
char audio_lang[4];
" that matches the --native-language. If there are no\n"
" matching audio tracks then the first matching\n"
" subtitle track is used instead.\n"
-
+ " --srt-file <string> SubRip SRT filename(s), separated by commas.\n"
+ " --srt-codeset Character codeset(s) that the SRT file(s) are\n"
+ " <string> encoded in, separted by commas.\n"
+ " Use 'iconv -l' for a list of valid\n"
+ " codesets. If not specified latin1 is assumed\n"
+ " --srt-offset Offset in milli-seconds to apply to the SRT file(s)\n"
+ " <string> separted by commas. If not specified zero is assumed.\n"
+ " Offsets may be negative.\n"
+ " --srt-lang <string> Language as an iso639-2 code fra, eng, spa et cetera)\n"
+ " for the SRT file(s) separated by commas. If not specified\n"
+ " then 'und' is used.\n"
"\n"
#define SUB_BURNED 266
#define SUB_DEFAULT 267
#define NATIVE_DUB 268
+ #define SRT_FILE 269
+ #define SRT_CODESET 270
+ #define SRT_OFFSET 271
+ #define SRT_LANG 272
for( ;; )
{
{ "subtitle-forced", optional_argument, NULL, 'F' },
{ "subtitle-burned", optional_argument, NULL, SUB_BURNED },
{ "subtitle-default", optional_argument, NULL, SUB_DEFAULT },
+ { "srt-file", required_argument, NULL, SRT_FILE },
+ { "srt-codeset", required_argument, NULL, SRT_CODESET },
+ { "srt-offset", required_argument, NULL, SRT_OFFSET },
+ { "srt-lang", required_argument, NULL, SRT_LANG },
{ "native-language", required_argument, NULL,'N' },
{ "native-dub", no_argument, NULL, NATIVE_DUB },
-
{ "encoder", required_argument, NULL, 'e' },
{ "aencoder", required_argument, NULL, 'E' },
{ "two-pass", no_argument, NULL, '2' },
case NATIVE_DUB:
native_dub = 1;
break;
+ case SRT_FILE:
+ srtfile = str_split( optarg, "," );
+ break;
+ case SRT_CODESET:
+ srtcodeset = str_split( optarg, "," );
+ break;
+ case SRT_OFFSET:
+ srtoffset = str_split( optarg, "," );
+ break;
+ case SRT_LANG:
+ srtlang = str_split( optarg, "," );
+ break;
case '2':
twoPass = 1;
break;