diff options
author | jstebbins <[email protected]> | 2011-03-31 00:05:23 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2011-03-31 00:05:23 +0000 |
commit | 4ffa2d38a93c0026603bc5595eee9615395bc0d9 (patch) | |
tree | a492d28b8df7d82664f4f21de9d916708c7354b1 /libhb/decssasub.c | |
parent | d5efaf404899a7b3738bae7bd7910066bf7ff4e6 (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/decssasub.c')
-rw-r--r-- | libhb/decssasub.c | 105 |
1 files changed, 94 insertions, 11 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; } |