ASS_Renderer *renderer;
ASS_Track *ssaTrack;
int readOrder;
+
+ hb_job_t *job;
};
typedef enum {
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'
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();
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;
}
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;
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;
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?");