All pastes #979694 Raw Edit

srt patch for handbrake

public diff v1 · immutable
·published 2008-04-10 15:13 UTC
rendered paste body
Index: test/test.c===================================================================--- test/test.c	(revision 1399)+++ test/test.c	(working copy)@@ -78,6 +78,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;@@ -258,6 +259,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" ); @@ -1126,6 +1128,12 @@                 job->native_language = strdup( native_language );             } +            if( srt != NULL && *srt != '\0' )+            {+                job->srt = 1;+                job->srt_file = srt;+            }+             if( job->mux )             {                 job->mux = mux;@@ -1408,6 +1416,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" @@ -1569,6 +1578,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' },@@ -1606,7 +1616,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 )         {@@ -1764,6 +1774,9 @@             case 'N':                 native_language = strdup( optarg );                 break;+            case '3':+                srt = strdup( optarg );+                break;             case '2':                 twoPass = 1;                 break;Index: libhb/Jamfile===================================================================--- libhb/Jamfile	(revision 1399)+++ libhb/Jamfile	(working copy)@@ -11,7 +11,7 @@ demuxmpeg.c fifo.c render.c reader.c muxcommon.c muxmp4.c sync.c stream.c decsub.c deca52.c decdca.c encfaac.c declpcm.c encx264.c decavcodec.c encxvid.c muxavi.c enclame.c muxogm.c encvorbis.c dvd.c muxmkv.c deblock.c deinterlace.c -denoise.c detelecine.c lang.c enctheora.c ;+denoise.c detelecine.c lang.c enctheora.c srt.c ;  Library libhb : $(LIBHB_SRC) ; Index: libhb/muxmp4.c===================================================================--- libhb/muxmp4.c	(revision 1399)+++ libhb/muxmp4.c	(working copy)@@ -9,6 +9,8 @@  #include "hb.h" +#include "srt.h"+ void AddIPodUUID(MP4FileHandle, MP4TrackId);  struct hb_mux_object_s@@ -28,6 +30,9 @@     int current_chapter;     uint64_t chapter_duration; +    /* Subtitle stuff for muxing */+    MP4TrackId subtitle_track;+     /* Sample rate of the first audio track.      * Used for the timescale      */@@ -130,7 +135,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 offset,+							const long duration)+{+    if (duration <= 0)+        return;+    +    if (offset) {+        // Write the offset...+        u_int8_t empty[2] = {0,0};+        MP4WriteSample(file,+                       track,+                       empty,+                       2,+                       offset,+                       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@@ -350,6 +462,26 @@         m->current_chapter = job->chapter_start; 	} +	printf("[Srt] implementation");+    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);+        +        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);@@ -401,6 +533,7 @@                 hb_error("Failed to write to output file, disk full?");                 *job->die = 1;             }+                         free(sample);             m->current_chapter = buf->new_chap;             m->chapter_duration += duration;@@ -481,6 +614,7 @@             hb_error("Failed to write to output file, disk full?");             *job->die = 1;         }+                 free(sample);     } @@ -523,4 +657,3 @@     m->job       = job;     return m; }-Index: libhb/srt.c===================================================================--- libhb/srt.c	(revision 0)+++ libhb/srt.c	(revision 0)@@ -0,0 +1,135 @@+#include "srt.h"+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++struct start_and_end {+	unsigned long start, end;+};++static struct start_and_end read_time_from_string(const char* timeString) {+	// for ex. 00:00:15,248 --> 00:00:16,545+	+	long houres1, minutes1, seconds1, milliseconds1,+	houres2, minutes2, seconds2, milliseconds2;+	+	sscanf(timeString, "%ld:%ld:%ld,%ld --> %ld:%ld:%ld,%ld\n",	&houres1, &minutes1, &seconds1, &milliseconds1,+		   &houres2, &minutes2, &seconds2, &milliseconds2);+	+	struct start_and_end result = {milliseconds1 + seconds1*1000 + minutes1*60000 + houres1*36000,+	milliseconds2 + seconds2*1000 + minutes2*60000 + houres2*36000};+	return result;+}++enum+{+	k_state_inEntry,+	k_state_potential_new_entry,+	k_state_timecode,+};++struct srt_entry_s* srt_readfile(const char* filename)+{+	FILE *file = fopen ( filename, "r" );+	+	if (file == NULL)+		return NULL;+	+	char line_buffer[1024];+	unsigned long	current_time = 0,+	number_of_entries = 0,+	current_state = k_state_potential_new_entry;+	+	struct srt_entry_s	*first_entry = malloc(sizeof(struct srt_entry_s)),+	*current_entry = first_entry;+	memset(first_entry, 0, sizeof(struct srt_entry_s));+	+	while (fgets(line_buffer,sizeof(line_buffer),file)) {+		switch (current_state)+		{+			case k_state_timecode:+			{+				struct start_and_end timing = read_time_from_string(line_buffer);			+				+				current_entry->duration = timing.end - timing.start;+				current_entry->offset = timing.start - current_time;+				+				current_time = timing.end;+				+				current_state = k_state_inEntry;+				continue;				+			}+				+			case k_state_inEntry:+			{+				// If the current line is empty, we assume this is the+				//	seperation betwene two entries. In case we are wrong,+				//	the mistake is corrected in the next state.+				if (strcmp(line_buffer, "\n") == 0 || strcmp(line_buffer, "\r\n") == 0) {					+					current_state = k_state_potential_new_entry;+					continue;+				}+				+				// Append the current line to the entry's text buffer;+				strncat(current_entry->text, line_buffer, 1024);+				+				break;				+			}+				+			case k_state_potential_new_entry:+			{+				char endpoint[] = "\0";+				const unsigned long potential_entry_number = strtol(line_buffer, (char**)&endpoint, 10);+				+				// Is this really new next entry begin?+				if (potential_entry_number == number_of_entries + 1) {+					// We actuall found the next entry - or a really rare error condition+					+					// The first entry was preallocated - all others are alloced here+					//	plus we overwrite zero-duration entries+					if (number_of_entries != 0) {+						current_entry->next = malloc(sizeof(struct srt_entry_s));						+						current_entry = current_entry->next;+					}+					+					memset(current_entry, 0, sizeof(struct srt_entry_s));+					+					++number_of_entries;+					current_state = k_state_timecode;+					continue;+				} else {+					// Well.. looks like we are in the wrong mode.. lets add the+					//	newline we misinterpreted...+					strncat(current_entry->text, "\n", 1024);+					current_state = k_state_inEntry;+				}+				+				break;+			}+		}+	}+	+	fclose ( file );+	+	// Since the number of entries is incremented when we find the next entry,+	//	we missed the lastone+	if (strlen(current_entry->text)) {+		++number_of_entries;+	}+	+	// No entries found - free the preallocaed firstone+	if (number_of_entries == 0) {+		free(first_entry);+		return NULL;+	}+	+	return first_entry;+}++void srt_free_entries(struct srt_entry_s* entries)+{+	if (entries && entries->next)+		srt_free_entries(entries->next);+	free(entries);+}+Index: libhb/srt.h===================================================================--- libhb/srt.h	(revision 0)+++ libhb/srt.h	(revision 0)@@ -0,0 +1,11 @@+#pragma once++struct srt_entry_s {+	long offset, duration;+	char text[1024];+	+	struct srt_entry_s* next;+};++struct srt_entry_s* srt_readfile(const char* filename);+void srt_free_entries(struct srt_entry_s* entries);Index: libhb/work.c===================================================================--- libhb/work.c	(revision 1399)+++ libhb/work.c	(working copy)@@ -337,6 +337,11 @@         }     } +    if( job->srt )+    {+        hb_log(" + SRT subtitles imported: %s", job->srt_file);+    }+         /* if we are doing passthru, and the input codec is not the same as the output      * codec, then remove this audio from the job */     /* otherwise, Bad Things will happen */Index: libhb/common.h===================================================================--- libhb/common.h	(revision 1399)+++ libhb/common.h	(working copy)@@ -193,6 +193,9 @@     int             subtitle;     int 			subtitleSmartAdjust; +    int             srt;+    char *          srt_file;+         /* Muxer settings          mux:  output file format          file: file path */Index: macosx/HandBrake.xcodeproj/project.pbxproj===================================================================--- macosx/HandBrake.xcodeproj/project.pbxproj	(revision 1399)+++ 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 1399)+++ 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,