summaryrefslogtreecommitdiffstats
path: root/libhb
diff options
context:
space:
mode:
authorjstebbins <[email protected]>2011-03-31 00:05:23 +0000
committerjstebbins <[email protected]>2011-03-31 00:05:23 +0000
commit4ffa2d38a93c0026603bc5595eee9615395bc0d9 (patch)
treea492d28b8df7d82664f4f21de9d916708c7354b1 /libhb
parentd5efaf404899a7b3738bae7bd7910066bf7ff4e6 (diff)
True SSA passthru for MKV.
We were converting SSA to UTF8 subs which looses a lot of formatting. Now we pass through the ssa unmodified and add all fonts as attachments to the mkv. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@3891 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb')
-rw-r--r--libhb/decssasub.c105
-rw-r--r--libhb/muxmkv.c32
2 files changed, 125 insertions, 12 deletions
diff --git a/libhb/decssasub.c b/libhb/decssasub.c
index ebdc6d25c..03fb495db 100644
--- a/libhb/decssasub.c
+++ b/libhb/decssasub.c
@@ -33,6 +33,8 @@ struct hb_work_private_s
ASS_Renderer *renderer;
ASS_Track *ssaTrack;
int readOrder;
+
+ hb_job_t *job;
};
typedef enum {
@@ -339,6 +341,81 @@ fail:
return NULL;
}
+static hb_buffer_t * ssa_to_mkv_ssa( hb_work_object_t * w, hb_buffer_t * in )
+{
+ hb_work_private_t * pv = w->private_data;
+ hb_buffer_t * out_last = NULL;
+ hb_buffer_t * out_first = NULL;
+
+ hb_buffer_realloc( in, in->size + 1 );
+ in->data[in->size] = '\0';
+
+ const char *EOL = "\r\n";
+ char *curLine, *curLine_parserData;
+ for ( curLine = strtok_r( (char *) in->data, EOL, &curLine_parserData );
+ curLine;
+ curLine = strtok_r( NULL, EOL, &curLine_parserData ) )
+ {
+ // Skip empty lines and spaces between adjacent CR and LF
+ if (curLine[0] == '\0')
+ continue;
+
+ int64_t in_start, in_stop;
+ if ( parse_timing_from_ssa_packet( curLine, &in_start, &in_stop ) )
+ continue;
+
+ int len = strlen(curLine);
+
+ // Convert the SSA line to MKV-SSA format
+ char *layerField = malloc( len );
+ int numPartsRead = sscanf( curLine, "Dialogue: %128[^,],", layerField );
+ if ( numPartsRead != 1 )
+ {
+ free( layerField );
+ continue;
+ }
+
+ char *styleToTextFields = (char *)find_field( (uint8_t*)curLine, (uint8_t*)curLine + len, 4 );
+ if ( styleToTextFields == NULL )
+ {
+ free( layerField );
+ continue;
+ }
+
+ // The output should always be shorter than the input
+ hb_buffer_t * out = hb_buffer_init( len );
+ char *mkvOut = (char*)out->data;
+ out->start = in_start;
+ out->stop = in_stop;
+
+ sprintf( mkvOut, "%d,%s,%s",
+ pv->readOrder++, layerField, styleToTextFields );
+
+ free( layerField );
+
+ len = strlen(mkvOut);
+ if ( len == 0 )
+ {
+ hb_buffer_close(&out);
+ }
+ else
+ {
+ out->size = len;
+ if ( out_last == NULL )
+ {
+ out_last = out_first = out;
+ }
+ else
+ {
+ out_last->next = out;
+ out_last = out;
+ }
+ }
+ }
+
+ return out_first;
+}
+
/*
* SSA line format:
* Dialogue: Marked,Start,End,Style,Name,MarginL,MarginR,MarginV,Effect,Text '\0'
@@ -515,6 +592,7 @@ static int decssaInit( hb_work_object_t * w, hb_job_t * job )
pv = calloc( 1, sizeof( hb_work_private_t ) );
w->private_data = pv;
+ pv->job = job;
if ( w->subtitle->config.dest == RENDERSUB ) {
pv->ssa = ass_library_init();
@@ -589,24 +667,29 @@ static int decssaInit( hb_work_object_t * w, hb_job_t * job )
static int decssaWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
hb_buffer_t ** buf_out )
{
+ hb_work_private_t * pv = w->private_data;
hb_buffer_t * in = *buf_in;
- hb_buffer_t * out_list = NULL;
#if SSA_VERBOSE_PACKETS
printf("\nPACKET(%"PRId64",%"PRId64"): %.*s\n", in->start/90, in->stop/90, in->size, in->data);
#endif
- if ( in->size > 0 ) {
- out_list = ssa_decode_packet(w, in);
- } else {
- out_list = hb_buffer_init( 0 );
+ if ( in->size <= 0 )
+ {
+ *buf_out = in;
+ *buf_in = NULL;
+ return HB_WORK_DONE;
}
-
- // Dispose the input packet, as it is no longer needed
- hb_buffer_close(&in);
-
- *buf_in = NULL;
- *buf_out = out_list;
+
+ if ( w->subtitle->config.dest == PASSTHRUSUB && pv->job->mux == HB_MUX_MKV )
+ {
+ *buf_out = ssa_to_mkv_ssa(w, in);
+ }
+ else
+ {
+ *buf_out = ssa_decode_packet(w, in);
+ }
+
return HB_WORK_OK;
}
diff --git a/libhb/muxmkv.c b/libhb/muxmkv.c
index 287f677fa..aed5940b4 100644
--- a/libhb/muxmkv.c
+++ b/libhb/muxmkv.c
@@ -48,6 +48,7 @@ static int MKVInit( hb_mux_object_t * m )
uint8_t *avcC = NULL;
uint8_t default_track_flag = 1;
+ uint8_t need_fonts = 0;
int avcC_len, i, j;
ogg_packet *ogg_headers[3];
mk_TrackConfig *track;
@@ -309,7 +310,15 @@ static int MKVInit( hb_mux_object_t * m )
track->codecPrivateSize = len + 1;
break;
case TEXTSUB:
- track->codecID = MK_SUBTITLE_UTF8;
+ if (subtitle->source == SSASUB)
+ {
+ track->codecID = MK_SUBTITLE_SSA;
+ need_fonts = 1;
+ track->codecPrivate = subtitle->extradata;
+ track->codecPrivateSize = subtitle->extradata_size;
+ }
+ else
+ track->codecID = MK_SUBTITLE_UTF8;
break;
default:
continue;
@@ -331,6 +340,27 @@ static int MKVInit( hb_mux_object_t * m )
mux_data->track = mk_createTrack(m->file, track);
}
+ if (need_fonts)
+ {
+ hb_list_t * list_attachment = job->title->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 )
+ {
+ mk_createAttachment(
+ m->file,
+ attachment->name,
+ NULL,
+ "application/x-truetype-font",
+ attachment->data,
+ attachment->size);
+ }
+ }
+ }
+
if( mk_writeHeader( m->file, "HandBrake " HB_PROJECT_VERSION) < 0 )
{
hb_error( "Failed to write to output file, disk full?");