rendered paste bodyIndex: test/test.c===================================================================--- test/test.c (revision 1364)+++ test/test.c (working copy)@@ -73,6 +73,7 @@ static int vfr = 0; static int mp4_optimize = 0; static int ipod_atom = 0;+static char * srt = NULL; /* Exit cleanly on Ctrl-C */ static volatile int die = 0;@@ -235,6 +236,7 @@ if( x264opts ) free (x264opts ); if( x264opts2 ) free (x264opts2 ); if (preset_name) free (preset_name);+ if (srt) free (srt); fprintf( stderr, "HandBrake has exited.\n" ); @@ -901,6 +903,12 @@ { job->native_language = strdup( native_language ); }+ + if( srt != NULL && *srt != '\0' )+ {+ job->srt = 1;+ job->srt_file = srt;+ } if( job->mux ) {@@ -1184,6 +1192,7 @@ " -N, --native-language Select subtitles with this language if it does not\n" " <string> match the Audio language. Provide the language's\n" " iso639-2 code (fre, eng, spa, dut, et cetera)\n"+ " -3 --srt <string> Indicate a filepath for loading text subtitles\n" " -m, --markers Add chapter markers (mp4 output format only)\n" "\n" @@ -1340,6 +1349,7 @@ { "subtitle-scan", no_argument, NULL, 'U' }, { "subtitle-forced", no_argument, NULL, 'F' }, { "native-language", required_argument, NULL,'N' },+ { "srt", required_argument, NULL, '3'}, { "encoder", required_argument, NULL, 'e' }, { "aencoder", required_argument, NULL, 'E' },@@ -1377,7 +1387,7 @@ int c; c = getopt_long( argc, argv,- "hvuC:f:4i:Io:t:Lc:m::a:6:s:UFN:e:E:2dD:789gpOP::w:l:n:b:q:S:B:r:R:Qx:TY:X:VZ:z",+ "hvuC:f:3:4i:Io:t:Lc:m::a:6:s:UFN:e:E:2dD:789gpOP::w:l:n:b:q:S:B:r:R:Qx:TY:X:VZ:z", long_options, &option_index ); if( c < 0 ) {@@ -1500,6 +1510,9 @@ case 'N': native_language = strdup( optarg ); break;+ case '3':+ srt = strdup( optarg );+ break; case '2': twoPass = 1; break;Index: libhb/muxmp4.c===================================================================--- libhb/muxmp4.c (revision 1364)+++ libhb/muxmp4.c (working copy)@@ -9,6 +9,8 @@ #include "hb.h" +#include "srt.h"+ void AddIPodUUID(MP4FileHandle, MP4TrackId); struct hb_mux_object_s@@ -27,6 +29,9 @@ MP4TrackId chapter_track; int current_chapter; uint64_t chapter_duration;+ + /* Subtitle stuff for muxing */+ MP4TrackId subtitle_track; }; struct hb_mux_data_s@@ -119,7 +124,114 @@ } +void MP4SetTrackYTranslation(const MP4FileHandle file,+ const MP4TrackId track,+ const u_int16_t translation)+{+ uint8_t* val;+ uint8_t nval[38];+ uint32_t *ptr32 = (uint32_t*) (nval + 2);+ uint32_t size;+ MP4GetTrackBytesProperty(file, track, "tkhd.reserved3", &val, &size);+ + memcpy(nval, val, size);+ + const uint32_t ytranslation = translation * 0x10000;+ +#ifdef WORDS_BIGENDIAN+ ptr32[7] = ytranslation;+#else+ /* we need to switch the endianness, as the file format expects big endian */+ ptr32[7] = ((ytranslation & 0x000000FF) << 24) + ((ytranslation & 0x0000FF00) << 8) + ((ytranslation & 0x00FF0000) >> 8) + ((ytranslation & 0xFF000000) >> 24);+#endif+ + MP4SetTrackBytesProperty(file, track, "tkhd.reserved3", nval, size); +}+ /**********************************************************************+ * MP4CreateSubtitleTrack+ **********************************************************************+ * Creates a new subtitle track+ *********************************************************************/+MP4TrackId MP4CreateSubtitleTrack(const MP4FileHandle file,+ const MP4TrackId refTrack,+ const uint16_t height,+ const uint16_t width,+ const uint16_t translation,+ const uint16_t language_code)+{+ const MP4TrackId subtitleTrack = MP4AddSubtitleTrack(file, refTrack);+ + MP4SetTrackIntegerProperty(file, subtitleTrack, "mdia.mdhd.language", language_code);+ MP4SetTrackFloatProperty(file, subtitleTrack, "tkhd.width", width);+ MP4SetTrackFloatProperty(file, subtitleTrack, "tkhd.height", height);+ + MP4SetTrackIntegerProperty(file, subtitleTrack, "tkhd.alternate_group", 2);+ + MP4SetTrackIntegerProperty(file, subtitleTrack, "mdia.minf.stbl.stsd.tx3g.defTextBoxTop", 0);+ MP4SetTrackIntegerProperty(file, subtitleTrack, "mdia.minf.stbl.stsd.tx3g.defTextBoxLeft", 0);+ MP4SetTrackIntegerProperty(file, subtitleTrack, "mdia.minf.stbl.stsd.tx3g.defTextBoxBottom", 50);+ MP4SetTrackIntegerProperty(file, subtitleTrack, "mdia.minf.stbl.stsd.tx3g.defTextBoxRight", 0);+ + MP4SetTrackIntegerProperty(file, subtitleTrack, "mdia.minf.stbl.stsd.tx3g.fontID", 1);+ MP4SetTrackIntegerProperty(file, subtitleTrack, "mdia.minf.stbl.stsd.tx3g.fontSize", 12);+ + MP4SetTrackIntegerProperty(file, subtitleTrack, "mdia.minf.stbl.stsd.tx3g.horizontalJustification", 1);+ MP4SetTrackIntegerProperty(file, subtitleTrack, "mdia.minf.stbl.stsd.tx3g.verticalJustification", 255);+ + MP4SetTrackIntegerProperty(file, subtitleTrack, "mdia.minf.stbl.stsd.tx3g.fontColorRed", 255);+ MP4SetTrackIntegerProperty(file, subtitleTrack, "mdia.minf.stbl.stsd.tx3g.fontColorGreen", 255);+ MP4SetTrackIntegerProperty(file, subtitleTrack, "mdia.minf.stbl.stsd.tx3g.fontColorBlue", 255);+ MP4SetTrackIntegerProperty(file, subtitleTrack, "mdia.minf.stbl.stsd.tx3g.fontColorAlpha", 255);+ + MP4SetTrackIntegerProperty(file, subtitleTrack, "mdia.minf.stbl.stsd.tx3g.bgColorRed", 0);+ MP4SetTrackIntegerProperty(file, subtitleTrack, "mdia.minf.stbl.stsd.tx3g.bgColorGreen", 0);+ MP4SetTrackIntegerProperty(file, subtitleTrack, "mdia.minf.stbl.stsd.tx3g.bgColorBlue", 0);+ MP4SetTrackIntegerProperty(file, subtitleTrack, "mdia.minf.stbl.stsd.tx3g.bgColorAlpha", 255);+ + MP4SetTrackYTranslation(file, subtitleTrack, translation);+ + MP4SetTrackTimeScale(file, subtitleTrack, 1000); // Set to ms++ return subtitleTrack;+}++void MP4WriteSubtitleSample(const MP4FileHandle file,+ const MP4TrackId track,+ const char* string,+ const long duration,+ const long offset)+{+ if (duration <= 0)+ return;+ + if (offset) {+ // Write the offset...+ u_int8_t empty[2] = {0,0};+ MP4WriteSample(file,+ track,+ empty,+ 2,+ duration,+ 0, true);+ }++ // .. and write the actual sample+ const size_t stringLength = strlen(string);+ u_int8_t buffer[1024];+ memcpy(buffer+2, string, strlen(string)); // strlen > 1024 -> booom+ buffer[0] = (stringLength >> 8) & 0xff;+ buffer[1] = stringLength & 0xff;+ + MP4WriteSample(file,+ track,+ buffer,+ stringLength + 2,+ duration,+ 0, true); +}++/********************************************************************** * MP4Init ********************************************************************** * Allocates hb_mux_data_t structures, create file and write headers@@ -183,12 +295,12 @@ return 0; } - mux_data->track = MP4AddH264VideoTrack( m->file, job->arate,- MP4_INVALID_DURATION, job->width, job->height,- job->config.h264.sps[1], /* AVCProfileIndication */- job->config.h264.sps[2], /* profile_compat */- job->config.h264.sps[3], /* AVCLevelIndication */- 3 ); /* 4 bytes length before each NAL unit */+ mux_data->track = MP4AddH264VideoTrack( m->file, job->arate,+ MP4_INVALID_DURATION, job->width, job->height,+ job->config.h264.sps[1], /* AVCProfileIndication */+ job->config.h264.sps[2], /* profile_compat */+ job->config.h264.sps[3], /* AVCLevelIndication */+ 3 ); /* 4 bytes length before each NAL unit */ MP4AddH264SequenceParameterSet( m->file, mux_data->track,@@ -196,11 +308,11 @@ MP4AddH264PictureParameterSet( m->file, mux_data->track, job->config.h264.pps, job->config.h264.pps_length ); - if( job->h264_level == 30 || job->ipod_atom)- {- hb_log("About to add iPod atom");- AddIPodUUID(m->file, mux_data->track);- }+ if( job->h264_level == 30 || job->ipod_atom)+ {+ hb_log("About to add iPod atom");+ AddIPodUUID(m->file, mux_data->track);+ } } else /* FFmpeg or XviD */@@ -246,18 +358,18 @@ MP4SetTrackFloatProperty(m->file, mux_data->track, "tkhd.width", job->width * (width / height)); } - /* firstAudioTrack will be used to reference the first audio track when we add a chapter track */- MP4TrackId firstAudioTrack = 0;+ /* firstAudioTrack will be used to reference the first audio track when we add a chapter track */+ MP4TrackId firstAudioTrack = 0; - /* add the audio tracks */+ /* add the audio tracks */ for( i = 0; i < hb_list_count( title->list_audio ); i++ ) {- static u_int8_t reserved2[16] = {- 0x00, 0x00, 0x00, 0x00,- 0x00, 0x00, 0x00, 0x00,- 0x00, 0x02, 0x00, 0x10,- 0x00, 0x00, 0x00, 0x00,- };+ static u_int8_t reserved2[16] = {+ 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x02, 0x00, 0x10,+ 0x00, 0x00, 0x00, 0x00,+ }; audio = hb_list_item( title->list_audio, i ); mux_data = malloc( sizeof( hb_mux_data_t ) );@@ -325,17 +437,39 @@ } - if (job->chapter_markers)+ if (job->chapter_markers) {- /* add a text track for the chapters */- MP4TrackId textTrack;- textTrack = MP4AddChapterTextTrack(m->file, firstAudioTrack);+ /* add a text track for the chapters */+ MP4TrackId textTrack;+ textTrack = MP4AddChapterTextTrack(m->file, firstAudioTrack); m->chapter_track = textTrack; m->chapter_duration = 0; m->current_chapter = job->chapter_start;- }-+ }+ + if (job->srt)+ {+ const uint16_t subtitleHeight = 60;+ m->subtitle_track = MP4CreateSubtitleTrack(m->file,+ mux_data->track,+ subtitleHeight,+ m->job->width,+ m->job->height - subtitleHeight,+ language_code);+ + +// char filename[] = job->srt_file;+ + struct srt_entry_s* subtitles = srt_readfile(job->srt_file);+ while (subtitles) {+ MP4WriteSubtitleSample(m->file, m->subtitle_track, subtitles->text, subtitles->offset, subtitles->duration); + subtitles = subtitles->next;+ }+ + srt_free_entries(subtitles);+ }+ /* Add encoded-by metadata listing version and build date */ char *tool_string; tool_string = (char *)malloc(80);@@ -387,6 +521,7 @@ hb_error("Failed to write to output file, disk full?"); *job->die = 1; }+ free(sample); m->current_chapter++; m->chapter_duration += duration;@@ -465,9 +600,10 @@ hb_error("Failed to write to output file, disk full?"); *job->die = 1; }+ free(sample); }-+ if (job->areBframes) { // Insert track edit to get A/V back in sync. The edit amount is@@ -507,4 +643,3 @@ m->job = job; return m; }-Index: libhb/work.c===================================================================--- libhb/work.c (revision 1364)+++ libhb/work.c (working copy)@@ -337,6 +337,11 @@ } } + if( job->srt )+ {+ hb_log(" + SRT subtitles imported: %s", job->srt_file);+ }+ if( job->audio_mixdowns[0] == HB_AMIXDOWN_AC3 || job->audio_mixdowns[1] == HB_AMIXDOWN_AC3 ) { /* Hard set correct sample rate for AC3 when libhbIndex: libhb/common.h===================================================================--- libhb/common.h (revision 1364)+++ libhb/common.h (working copy)@@ -252,6 +252,9 @@ int subtitle; int subtitleSmartAdjust; + int srt;+ char * srt_file;+ /* Muxer settings mux: output file format file: file path */Index: macosx/HandBrake.plist===================================================================--- macosx/HandBrake.plist (revision 1364)+++ macosx/HandBrake.plist (working copy)@@ -9,7 +9,7 @@ <key>CFBundleExecutable</key> <string>HandBrake</string> <key>CFBundleGetInfoString</key>- <string>0.9.2</string>+ <string>0.9.3svn1364M</string> <key>CFBundleIconFile</key> <string>HandBrake</string> <key>CFBundleIdentifier</key>@@ -21,11 +21,11 @@ <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key>- <string>0.9.2</string>+ <string>0.9.3svn1364M</string> <key>CFBundleSignature</key> <string>HB##</string> <key>CFBundleVersion</key>- <string>2008021900</string>+ <string>2008033001</string> <key>NSHumanReadableCopyright</key> <string>HandBrake Devs</string> <key>NSMainNibFile</key>Index: macosx/HandBrake.xcodeproj/project.pbxproj===================================================================--- macosx/HandBrake.xcodeproj/project.pbxproj (revision 1364)+++ macosx/HandBrake.xcodeproj/project.pbxproj (working copy)@@ -90,6 +90,10 @@ 593034EC0BBA39A100172349 /* ChapterTitles.m in Sources */ = {isa = PBXBuildFile; fileRef = 593034EA0BBA39A100172349 /* ChapterTitles.m */; }; 59CBD2370BBB44DA004A3BE3 /* parsecsv.c in Sources */ = {isa = PBXBuildFile; fileRef = 59CBD2360BBB44DA004A3BE3 /* parsecsv.c */; }; 59CBD2650BBB4D1B004A3BE3 /* ChapterTitles.m in Sources */ = {isa = PBXBuildFile; fileRef = 593034EA0BBA39A100172349 /* ChapterTitles.m */; };+ 7495D9E40DA024CC00CDC473 /* srt.c in Sources */ = {isa = PBXBuildFile; fileRef = 7495D9E20DA024CC00CDC473 /* srt.c */; };+ 7495D9E50DA024CC00CDC473 /* srt.h in Headers */ = {isa = PBXBuildFile; fileRef = 7495D9E30DA024CC00CDC473 /* srt.h */; };+ 7495D9E60DA024CC00CDC473 /* srt.c in Sources */ = {isa = PBXBuildFile; fileRef = 7495D9E20DA024CC00CDC473 /* srt.c */; };+ 7495D9E70DA024CC00CDC473 /* srt.h in Headers */ = {isa = PBXBuildFile; fileRef = 7495D9E30DA024CC00CDC473 /* srt.h */; }; A22C85EC0D05D35000C10E36 /* HBPresets.h in Headers */ = {isa = PBXBuildFile; fileRef = A22C85EA0D05D35000C10E36 /* HBPresets.h */; }; A22C85ED0D05D35100C10E36 /* HBPresets.m in Sources */ = {isa = PBXBuildFile; fileRef = A22C85EB0D05D35000C10E36 /* HBPresets.m */; }; A25289E60D87A27D00461D5B /* enctheora.c in Sources */ = {isa = PBXBuildFile; fileRef = A25289E50D87A27D00461D5B /* enctheora.c */; };@@ -258,6 +262,8 @@ 593034E90BBA39A100172349 /* ChapterTitles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChapterTitles.h; sourceTree = "<group>"; }; 593034EA0BBA39A100172349 /* ChapterTitles.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ChapterTitles.m; sourceTree = "<group>"; }; 59CBD2360BBB44DA004A3BE3 /* parsecsv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = parsecsv.c; path = ../test/parsecsv.c; sourceTree = SOURCE_ROOT; };+ 7495D9E20DA024CC00CDC473 /* srt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = srt.c; path = ../libhb/srt.c; sourceTree = SOURCE_ROOT; };+ 7495D9E30DA024CC00CDC473 /* srt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = srt.h; path = ../libhb/srt.h; sourceTree = SOURCE_ROOT; }; A22C85EA0D05D35000C10E36 /* HBPresets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBPresets.h; sourceTree = "<group>"; }; A22C85EB0D05D35000C10E36 /* HBPresets.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBPresets.m; sourceTree = "<group>"; }; A25289E50D87A27D00461D5B /* enctheora.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = enctheora.c; path = ../libhb/enctheora.c; sourceTree = SOURCE_ROOT; };@@ -432,6 +438,8 @@ 526FBC8D0B4CA9F90064E04C /* libhb Sources */ = { isa = PBXGroup; children = (+ 7495D9E20DA024CC00CDC473 /* srt.c */,+ 7495D9E30DA024CC00CDC473 /* srt.h */, A25289E50D87A27D00461D5B /* enctheora.c */, B48359A70C82960500E04440 /* lang.c */, EAA526920C3B25D200944FF2 /* stream.c */,@@ -567,6 +575,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = (+ 7495D9E70DA024CC00CDC473 /* srt.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; };@@ -575,6 +584,7 @@ buildActionMask = 2147483647; files = ( 593034EB0BBA39A100172349 /* ChapterTitles.h in Headers */,+ 7495D9E50DA024CC00CDC473 /* srt.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; };@@ -789,6 +799,7 @@ FC8519550C59A02C0073812C /* deinterlace.c in Sources */, FC8519560C59A02C0073812C /* deblock.c in Sources */, FC8519570C59A02C0073812C /* detelecine.c in Sources */,+ 7495D9E60DA024CC00CDC473 /* srt.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };@@ -834,6 +845,7 @@ FC8519530C59A02C0073812C /* detelecine.c in Sources */, B48359A80C82960500E04440 /* lang.c in Sources */, A25289E60D87A27D00461D5B /* enctheora.c in Sources */,+ 7495D9E40DA024CC00CDC473 /* srt.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };Index: contrib/Jamfile===================================================================--- contrib/Jamfile (revision 1364)+++ contrib/Jamfile (working copy)@@ -227,6 +227,7 @@ LIBMP4V2_PATCH += "$(PATCH) -p1 < ../patch-mpeg4ip.patch && " ; LIBMP4V2_PATCH += "$(PATCH) -p1 < ../patch-mpeg4ip-nasm-2.00-configure.patch && " ; LIBMP4V2_PATCH += "$(PATCH) -p1 < ../patch-mpeg4ip-ac3.patch && " ;+ LIBMP4V2_PATCH += "$(PATCH) -p1 < ../patch-mpeg4ip-srt.patch && " ; Depends $(<) : $(>) ; Depends lib : $(<) ; }Index: contrib/patch-mpeg4ip-srt.patch===================================================================--- contrib/patch-mpeg4ip-srt.patch (revision 0)+++ contrib/patch-mpeg4ip-srt.patch (revision 0)@@ -0,0 +1,406 @@+--- mpeg4ip/lib/mp4v2/Makefile.in 2008-03-30 16:58:59.000000000 -0400++++ mpeg4ip-patched/lib/mp4v2/Makefile.in 2008-03-30 16:56:50.000000000 -0400+@@ -55,7 +55,7 @@+ am_libmp4v2_la_OBJECTS = 3gp.lo atom_amr.lo atom_avc1.lo atom_avcC.lo \+ atom_d263.lo atom_damr.lo atom_dref.lo atom_elst.lo \+ atom_enca.lo atom_encv.lo atom_free.lo atom_ftyp.lo \+- atom_gmin.lo atom_text.lo atom_ac3.lo \++ atom_gmin.lo atom_text.lo atom_ac3.lo atom_tx3g.lo atom_ftab.lo atom_nmhd.lo \+ atom_hdlr.lo atom_hinf.lo atom_hnti.lo atom_href.lo \+ atom_mdat.lo atom_mdhd.lo atom_meta.lo atom_mp4a.lo \+ atom_mp4s.lo atom_mp4v.lo atom_mvhd.lo atom_pasp.lo atom_root.lo \+@@ -83,6 +83,7 @@+ @AMDEP_TRUE@ ./$(DEPDIR)/atom_enca.Plo \+ @AMDEP_TRUE@ ./$(DEPDIR)/atom_encv.Plo \+ @AMDEP_TRUE@ ./$(DEPDIR)/atom_free.Plo \++@AMDEP_TRUE@ ./$(DEPDIR)/atom_ftab.Plo \+ @AMDEP_TRUE@ ./$(DEPDIR)/atom_ftyp.Plo \+ @AMDEP_TRUE@ ./$(DEPDIR)/atom_gmin.Plo \+ @AMDEP_TRUE@ ./$(DEPDIR)/atom_hdlr.Plo \+@@ -96,6 +97,7 @@+ @AMDEP_TRUE@ ./$(DEPDIR)/atom_mp4s.Plo \+ @AMDEP_TRUE@ ./$(DEPDIR)/atom_mp4v.Plo \+ @AMDEP_TRUE@ ./$(DEPDIR)/atom_mvhd.Plo \++@AMDEP_TRUE@ ./$(DEPDIR)/atom_nmhd.Plo \+ @AMDEP_TRUE@ ./$(DEPDIR)/atom_root.Plo ./$(DEPDIR)/atom_rtp.Plo \+ @AMDEP_TRUE@ ./$(DEPDIR)/atom_pasp.Plo \+ @AMDEP_TRUE@ ./$(DEPDIR)/atom_s263.Plo ./$(DEPDIR)/atom_sdp.Plo \+@@ -112,6 +114,7 @@+ @AMDEP_TRUE@ ./$(DEPDIR)/atom_tkhd.Plo \+ @AMDEP_TRUE@ ./$(DEPDIR)/atom_treftype.Plo \+ @AMDEP_TRUE@ ./$(DEPDIR)/atom_trun.Plo \++@AMDEP_TRUE@ ./$(DEPDIR)/atom_tx3g.Plo \+ @AMDEP_TRUE@ ./$(DEPDIR)/atom_udta.Plo ./$(DEPDIR)/atom_url.Plo \+ @AMDEP_TRUE@ ./$(DEPDIR)/atom_urn.Plo \+ @AMDEP_TRUE@ ./$(DEPDIR)/atom_video.Plo \+@@ -354,6 +357,7 @@+ atom_enca.cpp \+ atom_encv.cpp \+ atom_free.cpp \++ atom_ftab.cpp \+ atom_ftyp.cpp \+ atom_gmin.cpp \+ atom_hdlr.cpp \+@@ -367,6 +371,7 @@+ atom_mp4s.cpp \+ atom_mp4v.cpp \+ atom_mvhd.cpp \++ atom_nmhd.cpp \+ atom_pasp.cpp \+ atom_root.cpp \+ atom_rtp.cpp \+@@ -386,6 +391,7 @@+ atom_tkhd.cpp \+ atom_treftype.cpp \+ atom_trun.cpp \++ atom_tx3g.cpp \+ atom_udta.cpp \+ atom_url.cpp \+ atom_urn.cpp \+@@ -510,6 +516,7 @@+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_enca.Plo@am__quote@+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_encv.Plo@am__quote@+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_free.Plo@am__quote@++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_ftab.Plo@am__quote@+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_ftyp.Plo@am__quote@+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_gmin.Plo@am__quote@+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_hdlr.Plo@am__quote@+@@ -523,6 +530,7 @@+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_mp4s.Plo@am__quote@+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_mp4v.Plo@am__quote@+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_mvhd.Plo@am__quote@++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_nmhd.Plo@am__quote@+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_pasp.Plo@am__quote@+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_root.Plo@am__quote@+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_rtp.Plo@am__quote@+@@ -541,6 +549,7 @@+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_tkhd.Plo@am__quote@+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_treftype.Plo@am__quote@+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_trun.Plo@am__quote@++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_tx3g.Plo@am__quote@+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_udta.Plo@am__quote@+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_url.Plo@am__quote@+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_urn.Plo@am__quote@+--- mpeg4ip/lib/mp4v2/Makefile.am 2008-03-30 16:58:59.000000000 -0400++++ mpeg4ip-patched/lib/mp4v2/Makefile.am 2008-03-30 16:47:28.000000000 -0400+@@ -22,6 +22,7 @@+ atom_encv.cpp \+ atom_free.cpp \+ atom_ftyp.cpp \++ atom_ftab.cpp \+ atom_gmin.cpp \+ atom_hdlr.cpp \+ atom_hinf.cpp \+@@ -35,6 +36,7 @@+ atom_mp4v.cpp \+ atom_mvhd.cpp \+ atom_name.cpp \++ atom_nmhd.cpp \+ atom_pasp.cpp \+ atom_root.cpp \+ atom_rtp.cpp \+@@ -53,6 +55,7 @@+ atom_tfhd.cpp \+ atom_tkhd.cpp \+ atom_treftype.cpp \++ atom_tx3g.cpp \+ atom_trun.cpp \+ atom_udta.cpp \+ atom_url.cpp \+Index: mpeg4ip/lib/mp4v2/mp4file.h+===================================================================+--- mpeg4ip/lib/mp4v2/mp4file.h (revision 4)++++ mpeg4ip/lib/mp4v2/mp4file.h (working copy)+@@ -303,6 +303,7 @@+ MP4TrackId AddHintTrack(MP4TrackId refTrackId);+ MP4TrackId AddTextTrack(MP4TrackId refTrackId);+ MP4TrackId AddChapterTextTrack(MP4TrackId refTrackId);++ MP4TrackId AddSubtitleTrack(MP4TrackId refTrackId);+ + MP4TrackId AddPixelAspectRatio(MP4TrackId trackId, u_int32_t hSpacing, u_int32_t vSpacing);+ +Index: mpeg4ip/lib/mp4v2/atom_nmhd.cpp+===================================================================+--- mpeg4ip/lib/mp4v2/atom_nmhd.cpp (revision 0)++++ mpeg4ip/lib/mp4v2/atom_nmhd.cpp (revision 0)+@@ -0,0 +1,25 @@++/*++ * The contents of this file are subject to the Mozilla Public++ * License Version 1.1 (the "License"); you may not use this file++ * except in compliance with the License. You may obtain a copy of++ * the License at http://www.mozilla.org/MPL/++ * ++ * Software distributed under the License is distributed on an "AS++ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or++ * implied. See the License for the specific language governing++ * rights and limitations under the License.++ * ++ * The Original Code is MPEG4IP.++ * ++ * The Initial Developer of the Original Code is Cisco Systems Inc.++ * Portions created by Cisco Systems Inc. are++ * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved.++ */++++#include "mp4common.h"++++MP4NmhdAtom::MP4NmhdAtom()++ : MP4Atom("nmhd") ++{++ AddVersionAndFlags();++}+\ No newline at end of file+Index: mp4atom.cpp+===================================================================+--- mpeg4ip/lib/mp4v2/mp4atom.cpp (revision 4)++++ mpeg4ip/lib/mp4v2/mp4atom.cpp (working copy)+@@ -120,6 +120,8 @@+ pAtom = new MP4FreeAtom();+ } else if (ATOMID(type) == ATOMID("ftyp")) {+ pAtom = new MP4FtypAtom();++ } else if (ATOMID(type) == ATOMID("ftab")) {++ pAtom = new MP4FtabAtom();+ }+ break;+ case 'g':+@@ -176,6 +178,8 @@+ case 'n':+ if (ATOMID(type) == ATOMID("name")) { // iTunes+ pAtom = new MP4NameAtom();++ } else if (ATOMID(type) == ATOMID("nmhd")) {++ pAtom = new MP4NmhdAtom();+ }+ break;+ case 'r':+@@ -216,6 +220,8 @@+ case 't':+ if (ATOMID(type) == ATOMID("text")) {+ pAtom = new MP4TextAtom();++ } else if (ATOMID(type) == ATOMID("tx3g")) {++ pAtom = new MP4Tx3gAtom();+ } else if (ATOMID(type) == ATOMID("tkhd")) {+ pAtom = new MP4TkhdAtom();+ } else if (ATOMID(type) == ATOMID("tfhd")) {+Index: mpeg4ip/lib/mp4v2/mp4.cpp+===================================================================+--- mpeg4ip/lib/mp4v2/mp4.cpp (revision 4)++++ mpeg4ip/lib/mp4v2/mp4.cpp (working copy)+@@ -973,6 +973,21 @@+ return MP4_INVALID_TRACK_ID;+ }+ ++extern "C" MP4TrackId MP4AddSubtitleTrack(++ MP4FileHandle hFile, MP4TrackId refTrackId)++{++ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {++ try {++ return ((MP4File*)hFile)->AddSubtitleTrack(refTrackId);++ }++ catch (MP4Error* e) {++ PRINT_ERROR(e);++ delete e;++ }++ }++ return MP4_INVALID_TRACK_ID;++}+++ extern "C" MP4TrackId MP4AddChapterTextTrack(+ MP4FileHandle hFile, MP4TrackId refTrackId)+ {+Index: mpeg4ip/lib/mp4v2/atom_tx3g.cpp+===================================================================+--- mpeg4ip/lib/mp4v2/atom_tx3g.cpp (revision 0)++++ mpeg4ip/lib/mp4v2/atom_tx3g.cpp (revision 0)+@@ -0,0 +1,55 @@++/*++ * The contents of this file are subject to the Mozilla Public++ * License Version 1.1 (the "License"); you may not use this file++ * except in compliance with the License. You may obtain a copy of++ * the License at http://www.mozilla.org/MPL/++ * ++ * Software distributed under the License is distributed on an "AS++ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or++ * implied. See the License for the specific language governing++ * rights and limitations under the License.++ * ++ * The Original Code is MPEG4IP.++ * ++ * The Initial Developer of the Original Code is Cisco Systems Inc.++ * Portions created by Cisco Systems Inc. are++ * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved.++ */++++#include "mp4common.h"++++MP4Tx3gAtom::MP4Tx3gAtom() ++ : MP4Atom("tx3g") ++{++ AddReserved("reserved1", 4); /* 0 */++ AddReserved("reserved2", 2); /* 1 */++ ++ AddProperty(new MP4Integer16Property("dataReferenceIndex"));/* 2 */++ ++ AddProperty(new MP4Integer32Property("displayFlags")); /* 3 */++ AddProperty(new MP4Integer8Property("horizontalJustification")); /* 4 */++ AddProperty(new MP4Integer8Property("verticalJustification")); /* 5 */++++ AddProperty(new MP4Integer8Property("bgColorRed")); /* 6 */++ AddProperty(new MP4Integer8Property("bgColorGreen")); /* 7 */++ AddProperty(new MP4Integer8Property("bgColorBlue")); /* 8 */++ AddProperty(new MP4Integer8Property("bgColorAlpha")); /* 9 */++++ AddProperty(new MP4Integer16Property("defTextBoxTop")); /* 10 */++ AddProperty(new MP4Integer16Property("defTextBoxLeft")); /* 11 */++ AddProperty(new MP4Integer16Property("defTextBoxBottom")); /* 12 */++ AddProperty(new MP4Integer16Property("defTextBoxRight")); /* 13 */++ ++ AddProperty(new MP4Integer16Property("startChar")); /* 14 */++ AddProperty(new MP4Integer16Property("endChar")); /* 15 */++ AddProperty(new MP4Integer16Property("fontID")); /* 16 */++ AddProperty(new MP4Integer8Property("fontFace")); /* 17 */++ AddProperty(new MP4Integer8Property("fontSize")); /* 18 */++ ++ AddProperty(new MP4Integer8Property("fontColorRed")); /* 19 */++ AddProperty(new MP4Integer8Property("fontColorGreen")); /* 20 */++ AddProperty(new MP4Integer8Property("fontColorBlue")); /* 21 */++ AddProperty(new MP4Integer8Property("fontColorAlpha")); /* 22 */++ ++ ExpectChildAtom("ftab", Optional, Many);++}+Index: mpeg4ip/lib/mp4v2/atoms.h+===================================================================+--- mpeg4ip/lib/mp4v2/atoms.h (revision 4)++++ mpeg4ip/lib/mp4v2/atoms.h (working copy)+@@ -353,6 +353,16 @@+ void GenerateGmhdType();+ };+ ++class MP4Tx3gAtom : public MP4Atom {++public:++ MP4Tx3gAtom();++};++++class MP4FtabAtom : public MP4Atom {++public:++ MP4FtabAtom();++};+++ class MP4TfhdAtom : public MP4Atom {+ public:+ MP4TfhdAtom();+@@ -406,4 +416,9 @@+ void Generate();+ };+ ++class MP4NmhdAtom : public MP4Atom {++public:++ MP4NmhdAtom();++};+++ #endif /* __MP4_ATOMS_INCLUDED__ */+Index: mpeg4ip/lib/mp4v2/atom_ftab.cpp+===================================================================+--- mpeg4ip/lib/mp4v2/atom_ftab.cpp (revision 0)++++ mpeg4ip/lib/mp4v2/atom_ftab.cpp (revision 0)+@@ -0,0 +1,32 @@++/*++ * The contents of this file are subject to the Mozilla Public++ * License Version 1.1 (the "License"); you may not use this file++ * except in compliance with the License. You may obtain a copy of++ * the License at http://www.mozilla.org/MPL/++ * ++ * Software distributed under the License is distributed on an "AS++ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or++ * implied. See the License for the specific language governing++ * rights and limitations under the License.++ * ++ * The Original Code is MPEG4IP.++ * ++ * The Initial Developer of the Original Code is Cisco Systems Inc.++ * Portions created by Cisco Systems Inc. are++ * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved.++ */++++#include "mp4common.h"++++MP4FtabAtom::MP4FtabAtom()++ : MP4Atom("ftab") ++{++ MP4Integer16Property* pCount = new MP4Integer16Property("entryCount"); /* 0 */++ AddProperty(pCount);++++ MP4TableProperty* pTable = new MP4TableProperty("fontEntries", pCount); /* 1 */++ AddProperty(pTable);++++ pTable->AddProperty(new MP4Integer16Property("fontID")); /* 0 */++ pTable->AddProperty(new MP4StringProperty("name", true)); /* 1 */ ++}+Index: mpeg4ip/lib/mp4v2/mp4file.cpp+===================================================================+--- mpeg4ip/lib/mp4v2/mp4file.cpp (revision 4)++++ mpeg4ip/lib/mp4v2/mp4file.cpp (working copy)+@@ -1948,6 +1948,49 @@+ return trackId;+ }+ ++MP4TrackId MP4File::AddSubtitleTrack(MP4TrackId refTrackId)++{++ // validate reference track id++ FindTrackIndex(refTrackId);++ ++ MP4TrackId trackId = ++ AddTrack(MP4_TEXT_TRACK_TYPE, GetTrackTimeScale(refTrackId));++ ++ InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "nmhd", 0);++ ++ AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "tx3g");++ ++ MP4StringProperty* pHandlerTypeProperty;++ FindStringProperty(MakeTrackName(trackId, "mdia.hdlr.handlerType"),++ (MP4Property**)&pHandlerTypeProperty);++ pHandlerTypeProperty->SetValue("sbtl");++ ++ // Hardcoded crap... add the ftab atom and add one font entry++ MP4Atom* pFtabAtom = AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.tx3g"), "ftab");++ ++ ((MP4Integer16Property*)pFtabAtom->GetProperty(0))->IncrementValue();++ ++ MP4Integer16Property* pfontID = (MP4Integer16Property*)((MP4TableProperty*)pFtabAtom->GetProperty(1))->GetProperty(0);++ pfontID->AddValue(1);++ ++ MP4StringProperty* pName = (MP4StringProperty*)((MP4TableProperty*)pFtabAtom->GetProperty(1))->GetProperty(1);++ pName->AddValue("Arial");++ ++ ++ // stsd is a unique beast in that it has a count of the number ++ // of child atoms that needs to be incremented after we add the text atom++ MP4Integer32Property* pStsdCountProperty;++ FindIntegerProperty(++ MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"),++ (MP4Property**)&pStsdCountProperty);++ pStsdCountProperty->IncrementValue();++++ /* add the magic "text" atom to the generic media header */++// AddChildAtom(MakeTrackName(trackId, "mdia.minf.gmhd"), "text");++ ++ return trackId;++}+++ MP4TrackId MP4File::AddChapterTextTrack(MP4TrackId refTrackId)+ {+ // validate reference track id+Index: mpeg4ip/lib/mp4v2/mp4.h+===================================================================+--- mpeg4ip/lib/mp4v2/mp4.h (revision 4)++++ mpeg4ip/lib/mp4v2/mp4.h (working copy)+@@ -553,6 +553,10 @@+ MP4FileHandle hFile, + MP4TrackId refTrackId);+ ++MP4TrackId MP4AddSubtitleTrack(++ MP4FileHandle hFile,++ MP4TrackId refTrackId);++ + MP4TrackId MP4AddPixelAspectRatio(+ MP4FileHandle hFile, + MP4TrackId refTrackId,