📄 mpeg3demux.c
字号:
current_timecode = -1;
while(timecode = next_timecode(demuxer,
¤t_title,
¤t_timecode,
current_program))
{
timecode->absolute_start_time = current_time;
/*
* printf("mpeg3demux_assign_programs %p end: %f start: %f\n",
* timecode,
* timecode->end_time,
* timecode->start_time);
*/
current_time += fabs(timecode->end_time - timecode->start_time);
timecode->absolute_end_time = current_time;
}
}
//for(i = 0; i < demuxer->total_titles; i++) mpeg3_dump_title(demuxer->titles[i]);
demuxer->current_program = 0;
return 0;
}
int mpeg3demux_copy_titles(mpeg3_demuxer_t *dst, mpeg3_demuxer_t *src)
{
long i;
mpeg3_t *file = dst->file;
mpeg3_title_t *dst_title, *src_title;
dst->total_titles = src->total_titles;
dst->total_programs = src->total_programs;
for(i = 0; i < MPEG3_MAX_STREAMS; i++)
{
dst->astream_table[i] = src->astream_table[i];
dst->vstream_table[i] = src->vstream_table[i];
}
for(i = 0; i < src->total_titles; i++)
{
src_title = src->titles[i];
dst_title = dst->titles[i] = mpeg3_new_title(file, src->titles[i]->fs->path);
mpeg3_copy_title(dst_title, src_title);
}
mpeg3demux_open_title(dst, src->current_title);
dst->current_timecode = 0;
return 0;
}
/* ==================================================================== */
/* Entry points */
/* ==================================================================== */
mpeg3_demuxer_t* mpeg3_new_demuxer(mpeg3_t *file, int do_audio, int do_video, int stream_id)
{
mpeg3_demuxer_t *demuxer = calloc(1, sizeof(mpeg3_demuxer_t));
int i;
/* The demuxer will change the default packet size for its own use. */
demuxer->file = file;
demuxer->do_audio = do_audio;
demuxer->do_video = do_video;
/* Allocate buffer + padding */
demuxer->raw_data = calloc(1, MPEG3_RAW_SIZE);
demuxer->data_buffer = calloc(1, MPEG3_RAW_SIZE);
/* System specific variables */
demuxer->audio_pid = stream_id;
demuxer->video_pid = stream_id;
demuxer->astream = stream_id;
demuxer->vstream = stream_id;
demuxer->current_title = -1;
//printf("mpeg3_new_demuxer %f\n", demuxer->time);
return demuxer;
}
int mpeg3_delete_demuxer(mpeg3_demuxer_t *demuxer)
{
int i;
if(demuxer->current_title >= 0)
{
mpeg3io_close_file(demuxer->titles[demuxer->current_title]->fs);
}
for(i = 0; i < demuxer->total_titles; i++)
{
mpeg3_delete_title(demuxer->titles[i]);
}
free(demuxer->data_buffer);
free(demuxer->raw_data);
free(demuxer);
return 0;
}
/* Need a timecode table to do this */
double mpeg3demux_length(mpeg3_demuxer_t *demuxer)
{
mpeg3_title_t *title;
int i, j;
double length;
for(i = demuxer->total_titles - 1; i >= 0; i--)
{
title = demuxer->titles[i];
for(j = title->timecode_table_size - 1; j >= 0; j--)
{
if(title->timecode_table[j].program == demuxer->current_program)
{
/*
* printf("mpeg3demux_length %f %f %f %f\n",
* title->timecode_table[j].end_time,
* title->timecode_table[j].start_time,
* title->timecode_table[j].absolute_start_time,
* title->timecode_table[j].end_time - title->timecode_table[j].start_time);
*/
return title->timecode_table[j].end_time -
title->timecode_table[j].start_time +
title->timecode_table[j].absolute_start_time;
}
}
}
return 1;
}
int mpeg3demux_eof(mpeg3_demuxer_t *demuxer)
{
if(demuxer->current_title >= 0)
{
if(mpeg3io_eof(demuxer->titles[demuxer->current_title]->fs) &&
demuxer->current_title >= demuxer->total_titles - 1)
return 1;
}
return 0;
}
int mpeg3demux_bof(mpeg3_demuxer_t *demuxer)
{
if(demuxer->current_title >= 0)
{
if(mpeg3io_bof(demuxer->titles[demuxer->current_title]->fs) &&
demuxer->current_title <= 0)
return 1;
}
return 0;
}
void mpeg3demux_start_reverse(mpeg3_demuxer_t *demuxer)
{
demuxer->reverse = 1;
}
void mpeg3demux_start_forward(mpeg3_demuxer_t *demuxer)
{
demuxer->reverse = 0;
}
/* Seek to a byte in the current title */
int mpeg3demux_seek_byte(mpeg3_demuxer_t *demuxer, int64_t byte)
{
long current_position;
mpeg3_t *file = demuxer->file;
mpeg3_title_t *title = demuxer->titles[demuxer->current_title];
demuxer->data_position = 0;
demuxer->data_size = 0;
demuxer->error_flag = mpeg3io_seek(title->fs, byte);
if(!demuxer->error_flag &&
file->is_transport_stream &&
file->packet_size)
{
/* Get on a packet boundary only for transport streams. */
current_position = mpeg3io_tell(title->fs);
if(byte % file->packet_size)
{
demuxer->error_flag |= mpeg3io_seek(title->fs,
current_position -
(current_position % file->packet_size));
}
}
// Get current cell
for(demuxer->current_timecode = 0;
demuxer->current_timecode < title->timecode_table_size;
demuxer->current_timecode++)
{
if(title->timecode_table[demuxer->current_timecode].start_byte <= byte &&
title->timecode_table[demuxer->current_timecode].end_byte > byte)
{
break;
}
}
if(demuxer->current_timecode >= title->timecode_table_size)
demuxer->current_timecode = title->timecode_table_size - 1;
return demuxer->error_flag;
}
int mpeg3demux_seek_end(mpeg3_demuxer_t *demuxer)
{
mpeg3demux_open_title(demuxer, demuxer->total_titles - 1);
demuxer->current_timecode = 0;
return mpeg3demux_seek_byte(demuxer, demuxer->titles[demuxer->current_title]->total_bytes);
}
int mpeg3demux_seek_start(mpeg3_demuxer_t *demuxer)
{
mpeg3demux_open_title(demuxer, 0);
demuxer->current_timecode = 0;
return mpeg3demux_seek_byte(demuxer, 0);
}
/* For programs streams and toc seek to a time */
int mpeg3demux_seek_time(mpeg3_demuxer_t *demuxer, double new_time)
{
int i, j, done = 0, result = 0;
int64_t byte_offset, new_byte_offset;
double guess = 0, minimum = 65535;
mpeg3_title_t *title;
mpeg3demux_timecode_t *timecode;
demuxer->error_flag = 0;
i = 0;
j = 0;
title = demuxer->titles[i];
timecode = &title->timecode_table[j];
/* Get the title and timecode of the new position */
while(!demuxer->error_flag &&
!(timecode->absolute_start_time <= new_time &&
timecode->absolute_end_time > new_time &&
timecode->program == demuxer->current_program))
{
/* Next timecode */
j++;
if(j >= title->timecode_table_size)
{
i++;
j = 0;
if(i >= demuxer->total_titles)
{
demuxer->error_flag = 1;
return 1;
}
}
title = demuxer->titles[i];
timecode = &title->timecode_table[j];
}
//printf("mpeg3demux_seek_time 1 %d %f %f %f\n", i, timecode->absolute_start_time, timecode->absolute_end_time, new_time);
if(demuxer->current_title != i)
mpeg3demux_open_title(demuxer, i);
/* Guess the new byte position by interpolating */
demuxer->current_timecode = j;
byte_offset = ((new_time - timecode->absolute_start_time) /
(timecode->absolute_end_time - timecode->absolute_start_time) *
(timecode->end_byte - timecode->start_byte) +
timecode->start_byte);
//printf("mpeg3demux_seek_time %f %f\n", new_time, byte_offset);
/* Binary search */
while(!done && !result && byte_offset >= 0)
{
result = mpeg3demux_seek_byte(demuxer, (long)byte_offset);
//printf("seek_time 0 byte %.0f want %f result %d\n", byte_offset, new_time, result);
if(!result)
{
result = mpeg3_read_next_packet(demuxer);
// printf("seek_time 1 guess %f want %f\n", guess, new_time);
guess = demuxer->time + demuxer->time_offset;
if(fabs(new_time - guess) >= fabs(minimum)) done = 1;
else
{
minimum = guess - new_time;
new_byte_offset = byte_offset + ((new_time - guess) /
(timecode->end_time - timecode->start_time) *
(timecode->end_byte - timecode->start_byte));
if(fabs(new_byte_offset - byte_offset) < 1) done = 1;
byte_offset = new_byte_offset;
}
}
}
//printf("mpeg3demux_seek_time 1\n");
/* Get one packet before the packet just read */
if(!result && byte_offset > 0 && minimum > 0)
{
mpeg3_read_prev_packet(demuxer);
//printf("mpeg3demux_seek_time 2\n");
mpeg3_read_prev_packet(demuxer);
}
//printf("mpeg3demux_seek_time 3\n");
//printf("mpeg3demux_seek_time 2 %d %d %d\n", demuxer->current_title, demuxer->current_timecode, mpeg3demux_tell(demuxer));
demuxer->error_flag = result;
return result;
}
int mpeg3demux_seek_percentage(mpeg3_demuxer_t *demuxer, double percentage)
{
double total_bytes = 0;
double absolute_position;
long relative_position;
int i, new_title;
mpeg3_title_t *title;
demuxer->error_flag = 0;
/* Get the absolute byte position; */
for(i = 0; i < demuxer->total_titles; i++)
total_bytes += demuxer->titles[i]->total_bytes;
absolute_position = percentage * total_bytes;
/* Get the title the byte is inside */
for(new_title = 0, total_bytes = 0; new_title < demuxer->total_titles; new_title++)
{
total_bytes += demuxer->titles[new_title]->total_bytes;
if(absolute_position < total_bytes) break;
}
if(new_title >= demuxer->total_titles)
{
new_title = demuxer->total_titles - 1;
}
/* Got a title */
title = demuxer->titles[new_title];
total_bytes -= title->total_bytes;
relative_position = (long)(absolute_position - total_bytes);
/* Get the timecode the byte is inside */
for(demuxer->current_timecode = 0;
demuxer->current_timecode < title->timecode_table_size;
demuxer->current_timecode++)
{
if(title->timecode_table[demuxer->current_timecode].start_byte <= relative_position &&
title->timecode_table[demuxer->current_timecode].end_byte > relative_position)
{
break;
}
}
if(demuxer->current_timecode >= title->timecode_table_size)
demuxer->current_timecode = title->timecode_table_size - 1;
/* Get the nearest timecode in the same program */
while(demuxer->current_timecode < title->timecode_table_size - 1 &&
title->timecode_table[demuxer->current_timecode].program != demuxer->current_program)
{
demuxer->current_timecode++;
}
/*
* printf("seek percentage 1 %d %d %d %d\n", demuxer->current_title,
* demuxer->current_timecode,
* title->timecode_table[demuxer->current_timecode].start_byte,
* title->timecode_table[demuxer->current_timecode].end_byte);
*/
/* Open the new title and seek to the correct byte */
if(new_title != demuxer->current_title)
{
demuxer->error_flag = mpeg3demux_open_title(demuxer, new_title);
}
/*
* printf("seek percentage 2 %d %d %d %d\n", demuxer->current_title,
* demuxer->current_timecode,
* title->timecode_table[demuxer->current_timecode].start_byte,
* title->timecode_table[demuxer->current_timecode].end_byte);
*/
if(!demuxer->error_flag)
demuxer->error_flag = mpeg3io_seek(title->fs, relative_position);
return demuxer->error_flag;
}
// Lots of optimization errors
double mpeg3demux_tell_percentage(mpeg3_demuxer_t *demuxer)
{
double total_bytes = 0;
double position = 0;
int i;
demuxer->error_flag = 0;
position = mpeg3io_tell_gcc(demuxer->titles[demuxer->current_title]->fs);
for(i = 0; i < demuxer->total_titles; i++)
{
double new_bytes = mpeg3_total_bytes_gcc(demuxer->titles[i]);
if(i == demuxer->current_title)
{
position = mpeg3_add_double_gcc(total_bytes, position);
}
total_bytes = mpeg3_add_double_gcc(total_bytes, new_bytes);
}
return position / total_bytes;
}
double mpeg3demux_get_time(mpeg3_demuxer_t *demuxer)
{
return demuxer->time;
}
int64_t mpeg3demux_tell(mpeg3_demuxer_t *demuxer)
{
return mpeg3io_tell(demuxer->titles[demuxer->current_title]->fs);
}
int mpeg3demux_tell_title(mpeg3_demuxer_t *demuxer)
{
return demuxer->current_title;
}
int64_t mpeg3demuxer_total_bytes(mpeg3_demuxer_t *demuxer)
{
mpeg3_title_t *title = demuxer->titles[demuxer->current_title];
return title->total_bytes;
}
mpeg3_demuxer_t* mpeg3_get_demuxer(mpeg3_t *file)
{
if(file->is_program_stream || file->is_transport_stream)
{
if(file->total_astreams) return file->atrack[0]->demuxer;
else
if(file->total_vstreams) return file->vtrack[0]->demuxer;
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -