All pastes #963559 Raw Edit

libhb-subtitles.patch

public diff v1 · immutable
#963559 ·published 2008-03-30 17:37 UTC
rendered paste body
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@@ -335,7 +447,26 @@         m->chapter_duration = 0;         m->current_chapter = job->chapter_start; 	}-+	+	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[] = "/Users/ben/Developer/SrtParser/test.srt";+	struct srt_entry_s* subtitles = srt_readfile(filename);+	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,7 +518,8 @@                 hb_error("Failed to write to output file, disk full?");                 *job->die = 1;             }-            free(sample);+			+			free(sample);             m->current_chapter++;             m->chapter_duration += duration;         }@@ -465,9 +597,10 @@             hb_error("Failed to write to output file, disk full?");             *job->die = 1;         }-        free(sample);+		+		free(sample);     }-+	     if (job->areBframes)     {            // Insert track edit to get A/V back in sync.  The edit amount is@@ -507,4 +640,3 @@     m->job       = job;     return m; }-Index: libhb/srt.c===================================================================--- libhb/srt.c	(revision 0)+++ libhb/srt.c	(revision 0)@@ -0,0 +1,134 @@+#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, "%d:%d:%d,%d --> %d:%d:%d,%d\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);+}\ No newline at end of fileIndex: 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);\ No newline at end of file