Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions src/lib_ccx/mp4_rust_bridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,14 +222,14 @@ int ccx_mp4_process_cc_packet(struct lib_ccx_ctx *ctx, int sub_type_c608,

int ccx_mp4_process_tx3g_packet(struct lib_ccx_ctx *ctx,
unsigned char *data, unsigned int data_length,
long long dts, int cts_offset,
unsigned int timescale,
long long start_ms,
struct cc_subtitle *sub)
{
struct lib_cc_decode *dec_ctx = update_decoder_list(ctx);
struct encoder_ctx *enc_ctx = update_encoder_list(ctx);

set_current_pts(dec_ctx->timing, (dts + cts_offset) * MPEG_CLOCK_FREQ / timescale);
/* Keep the global timing pointer roughly in sync with this track. */
set_current_pts(dec_ctx->timing, start_ms * MPEG_CLOCK_FREQ / 1000);
set_fts(dec_ctx->timing);

/* tx3g format: 16-bit text length + UTF-8 text */
Expand All @@ -242,7 +242,7 @@ int ccx_mp4_process_tx3g_packet(struct lib_ccx_ctx *ctx,

/* Set up subtitle for deferred encoding */
sub->type = CC_TEXT;
sub->start_time = dec_ctx->timing->fts_now;
sub->start_time = start_ms;
if (sub->data != NULL)
free(sub->data);
sub->data = malloc(text_length + 1);
Expand All @@ -255,14 +255,13 @@ int ccx_mp4_process_tx3g_packet(struct lib_ccx_ctx *ctx,
return 0;
}

void ccx_mp4_flush_tx3g(struct lib_ccx_ctx *ctx, struct cc_subtitle *sub)
void ccx_mp4_flush_tx3g(struct lib_ccx_ctx *ctx, struct cc_subtitle *sub, long long end_ms)
{
struct lib_cc_decode *dec_ctx = update_decoder_list(ctx);
struct encoder_ctx *enc_ctx = update_encoder_list(ctx);

if (sub->data != NULL)
{
sub->end_time = dec_ctx->timing->fts_now;
sub->end_time = end_ms;
encode_sub(enc_ctx, sub);
}
}
Expand Down
18 changes: 10 additions & 8 deletions src/lib_ccx/mp4_rust_bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,28 +59,30 @@ extern "C"
/*
* Process a tx3g (3GPP timed text) subtitle sample.
*
* Subtitle times are taken explicitly from the packet timestamps instead of
* the global timing pointer, which can be far ahead of this track because
* packets from every track are interleaved.
*
* @param ctx CCExtractor library context
* @param data tx3g sample data
* @param data_length Length of the data
* @param dts Decoding timestamp
* @param cts_offset Composition time offset
* @param timescale Media timescale
* @param start_ms Subtitle start time in milliseconds
* @param sub Output subtitle structure
* @return 0 on success, non-zero on error
*/
int ccx_mp4_process_tx3g_packet(struct lib_ccx_ctx *ctx,
unsigned char *data, unsigned int data_length,
long long dts, int cts_offset,
unsigned int timescale,
long long start_ms,
struct cc_subtitle *sub);

/*
* Flush pending tx3g subtitle (encode the last one).
*
* @param ctx CCExtractor library context
* @param sub Output subtitle structure
* @param ctx CCExtractor library context
* @param sub Output subtitle structure
* @param end_ms Subtitle end time in milliseconds
*/
void ccx_mp4_flush_tx3g(struct lib_ccx_ctx *ctx, struct cc_subtitle *sub);
void ccx_mp4_flush_tx3g(struct lib_ccx_ctx *ctx, struct cc_subtitle *sub, long long end_ms);

/*
* Report progress for the MP4 demuxer.
Expand Down
40 changes: 31 additions & 9 deletions src/rust/src/demuxer/mp4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,11 @@ extern "C" {
ctx: *mut lib_ccx_ctx,
data: *mut u8,
data_length: c_uint,
dts: i64,
cts_offset: c_int,
timescale: c_uint,
start_ms: i64,
sub: *mut cc_subtitle,
) -> c_int;

fn ccx_mp4_flush_tx3g(ctx: *mut lib_ccx_ctx, sub: *mut cc_subtitle);
fn ccx_mp4_flush_tx3g(ctx: *mut lib_ccx_ctx, sub: *mut cc_subtitle, end_ms: i64);

fn ccx_mp4_report_progress(ctx: *mut lib_ccx_ctx, cur: c_uint, total: c_uint);

Expand Down Expand Up @@ -313,6 +311,8 @@ pub unsafe fn processmp4_rust(ctx: *mut lib_ccx_ctx, path: &CStr, sub: *mut cc_s

let mut packet_count: u32 = 0;
let mut has_tx3g = false;
let mut prev_tx3g_start_ms: i64 = -1;
let mut prev_tx3g_end_ms: i64 = -1;
let mut prev_dvdsub_pts: i64 = -1;
let mut prev_dvdsub_data: Vec<u8> = Vec::new();

Expand Down Expand Up @@ -397,20 +397,36 @@ pub unsafe fn processmp4_rust(ctx: *mut lib_ccx_ctx, path: &CStr, sub: *mut cc_s
}
TrackType::Tx3g => {
if pkt.size > 0 && !pkt.data.is_null() {
// Subtitle times are taken from the packet timestamps directly:
// the global timing pointer may already be past this subtitle
// because packets from every track are interleaved.
let start_ms = pts * 1000 / timescale as i64;
let end_ms = if pkt.duration > 0 {
start_ms + pkt.duration * 1000 / timescale as i64
} else {
-1
};
if has_tx3g {
ccx_mp4_flush_tx3g(ctx, sub);
// Fall back to the new subtitle's start when the previous
// sample had no duration information.
let flush_end_ms = if prev_tx3g_end_ms >= 0 {
prev_tx3g_end_ms
} else {
start_ms
};
ccx_mp4_flush_tx3g(ctx, sub, flush_end_ms);
}
let r = ccx_mp4_process_tx3g_packet(
ctx,
pkt.data,
pkt.size as c_uint,
dts,
cts_offset,
timescale,
start_ms,
sub,
);
if r == 0 {
has_tx3g = true;
prev_tx3g_start_ms = start_ms;
prev_tx3g_end_ms = end_ms;
mp4_ret = 1;
}
}
Expand Down Expand Up @@ -459,7 +475,13 @@ pub unsafe fn processmp4_rust(ctx: *mut lib_ccx_ctx, path: &CStr, sub: *mut cc_s

// Flush last tx3g subtitle
if has_tx3g {
ccx_mp4_flush_tx3g(ctx, sub);
let end_ms = if prev_tx3g_end_ms >= 0 {
prev_tx3g_end_ms
} else {
// Match the 5 second default used for the other subtitle paths.
prev_tx3g_start_ms + 5000
};
ccx_mp4_flush_tx3g(ctx, sub, end_ms);
}

// Flush last dvdsub packet (use 5s default duration)
Expand Down
Loading