📄 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 errorsdouble 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 + -