static hb_buffer_t * ssa_to_mkv_ssa( hb_work_object_t * w, hb_buffer_t * in ) { hb_buffer_t * out_last = NULL; hb_buffer_t * out_first = NULL; // Store NULL after the end of the buffer to make using string processing safe hb_buffer_realloc(in, ++in->size); in->data[in->size - 1] = '\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 ) ) { hb_buffer_t * out; out = ssa_decode_line_to_mkv_ssa( w, (uint8_t *) curLine, strlen( curLine ), in->sequence ); if( out ) { if ( out_last == NULL ) { out_last = out_first = out; } else { out_last->next = out; out_last = out; } } } return out_first; }
/* * Decodes a single SSA packet to one or more TEXTSUB or PICTURESUB subtitle packets. * * SSA packet format: * ( Dialogue: Marked,Start,End,Style,Name,MarginL,MarginR,MarginV,Effect,Text CR LF ) + * 1 2 3 4 5 6 7 8 9 10 */ static hb_buffer_t *ssa_decode_packet( hb_work_object_t * w, hb_buffer_t *in ) { // Store NULL after the end of the buffer to make using string processing safe hb_buffer_realloc(in, ++in->size); in->data[in->size - 1] = '\0'; hb_buffer_list_t list; hb_buffer_t *buf; hb_buffer_list_clear(&list); 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; // Decode an individual SSA line buf = ssa_decode_line_to_mkv_ssa(w, in, (uint8_t *)curLine, strlen(curLine)); hb_buffer_list_append(&list, buf); } return hb_buffer_list_clear(&list); }
/* * Decodes a single SSA packet to one or more TEXTSUB or PICTURESUB subtitle packets. * * SSA packet format: * ( Dialogue: Marked,Start,End,Style,Name,MarginL,MarginR,MarginV,Effect,Text CR LF ) + * 1 2 3 4 5 6 7 8 9 10 */ static hb_buffer_t *ssa_decode_packet( hb_work_object_t * w, hb_buffer_t *in ) { // Store NULL after the end of the buffer to make using string processing safe hb_buffer_realloc(in, ++in->size); in->data[in->size - 1] = '\0'; hb_buffer_t *out_list = NULL; hb_buffer_t **nextPtr = &out_list; 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; // Decode an individual SSA line hb_buffer_t *out; if ( w->subtitle->config.dest == PASSTHRUSUB ) { out = ssa_decode_line_to_utf8( (uint8_t *) curLine, strlen( curLine ), in->sequence ); if ( out == NULL ) continue; // We shouldn't be storing the extra NULL character, // but the MP4 muxer expects this, unfortunately. if (out->size > 0 && out->data[out->size - 1] != '\0') { hb_buffer_realloc(out, ++out->size); out->data[out->size - 1] = '\0'; } // If the input packet was non-empty, do not pass through // an empty output packet (even if the subtitle was empty), // as this would be interpreted as an end-of-stream if ( in->size > 0 && out->size == 0 ) { hb_buffer_close(&out); continue; } } else if ( w->subtitle->config.dest == RENDERSUB ) { out = ssa_decode_line_to_mkv_ssa( w, (uint8_t *) curLine, strlen( curLine ), in->sequence ); if ( out == NULL ) continue; } // Append 'out' to 'out_list' *nextPtr = out; nextPtr = &out->next; } // For point-to-point encoding, when the start time of the stream // may be offset, the timestamps of the subtitles must be offset as well. // // HACK: Here we are making the assumption that, under normal circumstances, // the output display time of the first output packet is equal to the // display time of the input packet. // // During point-to-point encoding, the display time of the input // packet will be offset to compensate. // // Therefore we offset all of the output packets by a slip amount // such that first output packet's display time aligns with the // input packet's display time. This should give the correct time // when point-to-point encoding is in effect. if (out_list && out_list->s.start > in->s.start) { int64_t slip = out_list->s.start - in->s.start; hb_buffer_t *out; out = out_list; while (out) { out->s.start -= slip; out->s.stop -= slip; out = out->next; } } return out_list; }