📄 mpeg2edit.c
字号:
return 0;
}
static int es_judge_read_gop_header_end(int code)
{
if(code == 0x00000100){ /* picture_start_code */
return 1;
}
return 0;
}
static int es_judge_read_picture_end(int code)
{
if(code == 0x00000100){ /* picture_start_code */
return 1;
}else if(code == 0x000001b3){ /* sequence_start_code */
return 1;
}else if(code == 0x000001b8){ /* gop_start_code */
return 1;
}else if(code == 0x000001b7){ /* sequence_end_code */
return 1;
}
return 0;
}
static void es_write_sequence_header(ES_SEQUENCE_HEADER *in, FILE *out)
{
fwrite_list(in->head, out);
}
static void es_write_gop_header(ES_GOP_HEADER *in, FILE *out)
{
fwrite_list(in->head, out);
}
static void es_write_picture(ES_PICTURE *in, FILE *out)
{
fwrite_list(in->head, out);
}
static void es_write_frame(ES_FRAME *in, FILE *out)
{
es_write_picture(&(in->fst), out);
es_write_picture(&(in->snd), out);
}
static void es_write_sequence_end_code(FILE *out)
{
unsigned char sequence_end_code[4] = {
0, 0, 1, 0xb7,
};
fwrite(sequence_end_code, 1, 4, out);
}
static void es_clear_sequence_header(ES_SEQUENCE_HEADER *seq)
{
clear_list(seq->head);
seq->head = NULL;
seq->length = 0;
}
static void es_clear_gop_header(ES_GOP_HEADER *gop)
{
clear_list(gop->head);
gop->head = NULL;
gop->length = 0;
}
static void es_clear_picture(ES_PICTURE *pic)
{
clear_list(pic->head);
pic->head = NULL;
pic->length = 0;
}
static void es_clear_frame(ES_FRAME *frm)
{
es_clear_picture(&(frm->fst));
es_clear_picture(&(frm->snd));
}
static void es_padding_picture(ES_PICTURE *pic)
{
padding_list(pic->head, 0);
}
static void es_padding_frame(ES_FRAME *frm)
{
es_padding_picture(&(frm->fst));
if(frm->snd.length){
es_padding_picture(&(frm->snd));
}
}
static int es_get_fps(ES_SEQUENCE_HEADER *seq)
{
int r;
int rate;
int scale;
int offset;
unsigned char code;
unsigned char pattern[4] = { 0, 0, 1, 0xb5 };
static const int rate_table[16] = {
0, 23976, 24, 25, 2997, 30, 50, 5994,
60, 0, 0, 0, 0, 0, 0, 0,
};
static const int scale_table[16] = {
1, 1000, 1, 1, 100, 1, 1, 100,
1, 1, 1, 1, 1, 1, 1, 1,
};
code = get_byte_list(seq->head, 7);
rate = rate_table[code & 0xf];
scale = scale_table[code & 0xf];
offset = find_list(seq->head, 12, pattern, 4);
while(offset > 0){
if( (get_byte_list(seq->head, offset+4) & 0xf0) == 0x10){
code = get_byte_list(seq->head, offset+9);
rate *= (((code >> 5) & 0x3) + 1);
scale *= (((code >> 3) & 0x3) + 1);
break;
}else{
offset = find_list(seq->head, offset+4, pattern, 4);
}
}
r = (rate+(scale-1))/scale;
return r;
}
static void es_set_timecode(ES_GOP_HEADER *gop, __int64 frame, int fps)
{
int hh;
int mm;
int ss;
int ff;
unsigned char c0,c1,c2,c3;
ff = (int)(frame % fps);
frame /= fps;
ss = (int)(frame % 60);
frame /= 60;
mm = (int)(frame % 60);
frame /= 60;
hh = (int)(frame % 24);
c0 = (unsigned char)( (hh << 2) + (mm >> 4) );
c1 = (unsigned char)( ((mm & 0x0f) << 4) + 0x08 + (ss >> 3) );
c2 = (unsigned char)( ((ss & 7) << 5) + (ff >> 1) );
c3 = (unsigned char)( (get_byte_list(gop->head, 7) & 0x7f) + ((ff & 1) << 7) );
set_byte_list(gop->head, 4, c0);
set_byte_list(gop->head, 5, c1);
set_byte_list(gop->head, 6, c2);
set_byte_list(gop->head, 7, c3);
}
static int es_get_closed_gop(ES_GOP_HEADER *gop)
{
int r;
r = (get_byte_list(gop->head, 7) & 0x40) >> 6;
return r;
}
static int es_get_broken_link(ES_GOP_HEADER *gop)
{
int r;
r = (get_byte_list(gop->head, 7) & 0x20) >> 5;
return r;
}
static void es_set_broken_link(ES_GOP_HEADER *gop, int broken_link)
{
unsigned char c;
c = (unsigned char)(get_byte_list(gop->head, 7) & 0xdf);
if(broken_link){
c |= 0x20;
}
set_byte_list(gop->head, 7, c);
}
static int es_get_picture_temporal_reference(ES_PICTURE *pic)
{
int r;
r = get_byte_list(pic->head, 4) << 2;
r += (get_byte_list(pic->head, 5) >> 6);
return r;
}
static void es_set_picture_temporal_reference(ES_PICTURE *pic, int temporal_reference)
{
unsigned char c0;
unsigned char c1;
temporal_reference &= 0x000003ff;
c0 = (unsigned char)(temporal_reference >> 2);
c1 = (unsigned char)( (get_byte_list(pic->head, 5) & 0x3f) + ((temporal_reference & 3) << 6) );
set_byte_list(pic->head, 4, c0);
set_byte_list(pic->head, 5, c1);
}
static int es_get_picture_coding_type(ES_PICTURE *pic)
{
int r;
r = (get_byte_list(pic->head, 5) >> 3) & 3;
return r;
}
static int es_get_picture_field_count(ES_PICTURE *pic)
{
int r;
int offset;
int code;
unsigned char pattern[4] = { 0, 0, 1, 0xb5 };
r = 2;
offset = find_list(pic->head, 8, pattern, 4);
while(offset > 0){
if( (get_byte_list(pic->head, offset+4) & 0xf0) == 0x80){
code = get_byte_list(pic->head, offset+6);
if( (code & 0x03) != 0x03 ){
return 1;
}
code = get_byte_list(pic->head, offset+7);
if( (code & 0x02) == 0x02 ){
return 3;
}
break;
}else{
offset = find_list(pic->head, offset+4, pattern, 4);
}
}
return r;
}
static int es_get_temporal_reference(ES_FRAME *frm)
{
return es_get_picture_temporal_reference(&(frm->fst));
}
static void es_set_temporal_reference(ES_FRAME *frm, int temporal_reference)
{
es_set_picture_temporal_reference(&(frm->fst), temporal_reference);
if(frm->snd.length){
es_set_picture_temporal_reference(&(frm->snd), temporal_reference);
}
}
static int es_get_coding_type(ES_FRAME *frm)
{
return es_get_picture_coding_type(&(frm->fst));
}
static int es_get_field_count(ES_FRAME *frm)
{
int r;
r = es_get_picture_field_count(&(frm->fst));
if(frm->snd.length){
r += es_get_picture_field_count(&(frm->snd));
}
return r;
}
/*-----------------------------------------------------------------*/
static int ps_open(const char *path, MPEG2EDIT *mpeg2edit)
{
BITSTREAM *bs;
bs = bs_open(path);
if(bs == NULL){
return 0;
}
bs_seek(bs, 0, SEEK_SET);
mpeg2edit->stream = bs;
mpeg2edit->edit = ps_edit;
mpeg2edit->close = ps_close;
return 1;
}
static void ps_edit(void *mpeg2edit, char *out_path, __int64 in, __int64 out)
{
BITSTREAM *bs;
FILE *file;
PS_PACK_LIST_ELEMENT *header;
PS_PACK_LIST_ELEMENT *header_tail;
PS_PACK_LIST_ELEMENT *other;
PS_PACK_LIST_ELEMENT *other_tail;
PS_PACK *system;
PS_PACK *video1;
PS_PACK *video2;
PS_PACK *previous;
PS_PACK *current;
PS_PROC_VIDEO_OPTION opt;
STREAM_ID_LIST audio_stream;
int status;
int stream_id;
ps_init_proc_video_option(&opt, in, out);
ps_init_stream_id_list(&audio_stream);
header = NULL;
header_tail = NULL;
other = NULL;
other_tail = NULL;
system = NULL;
video1 = NULL;
video2 = NULL;
stream_id = 0;
status = PS_WASTE_PACK;
bs = ((MPEG2EDIT *)mpeg2edit)->stream;
bs_seek(bs, 0, SEEK_SET);
bs_next_packet_prefix(bs);
current = (PS_PACK *)calloc(1, sizeof(PS_PACK));
previous = NULL;
while(current){
if(((MPEG2EDIT *)mpeg2edit)->callback(out_path, ps_get_current_percent(&opt)) != VF_OK){
break;
}
ps_read_pack(bs, current);
ps_set_pack_scr_length(previous, ps_get_system_clock_reference(current)-ps_get_system_clock_reference(previous));
previous = current;
if( (stream_id & 0xf0) != 0xe0 ){
stream_id = ps_get_video_stream_id(current);
ps_set_stream_id_proc_video_option(&opt, stream_id);
}
if( ps_find_system_header(current) ){
if(system){
ps_clear_pack(system);
free(system);
}
system = current;
}
if( ((stream_id & 0xf0) == 0xe0) && ps_find_stream(current, stream_id) ){
video2 = current;
if(video1){
status = ps_proc_video(video1, video2, &opt);
if(status & PS_OUTPUT_PACK){
if(system == video2){
system = (PS_PACK *)calloc(1, sizeof(PS_PACK));
ps_copy_system_header_pack(video2, system);
}
goto PS_EDIT_2ND_STEP;
}else if(status & PS_HEADER_PACK){
ps_clear_pack_list(header);
header = ps_add_pack_list(NULL, video1);
header_tail = header;
}else if(status & PS_HEADER_CHAIN_PACK){
header_tail = ps_add_pack_list(header_tail, video1);
}else{
ps_clear_pack(video1);
free(video1);
}
}
video1 = video2;
if(system == video1){
system = (PS_PACK *)calloc(1, sizeof(PS_PACK));
ps_copy_system_header_pack(video1, system);
}
}else if(! ps_find_system_header(current)){
if(ps_check_pack_chain(other_tail, current)){
other_tail = ps_add_pack_list(other_tail, current);
}else{
ps_clear_pack_list(other);
other = ps_add_pack_list(NULL, current);
other_tail = other;
}
}
if(! bs_next_packet_prefix(bs) ){
break;
}
if( bs_read_bits(bs, 32) == 0x000001ba ){
current = (PS_PACK *)calloc(1, sizeof(PS_PACK));
}else{
current = NULL;
}
}
ps_clear_pack_list(header);
ps_clear_pack_list(other);
ps_clear_pack(system);
free(system);
ps_clear_pack(video1);
free(video1);
return;
PS_EDIT_2ND_STEP:
file = fopen(out_path, "wb");
if(file == NULL){
ps_clear_pack_list(header);
ps_clear_pack_list(other);
ps_clear_pack(system);
free(system);
ps_clear_pack(video1);
free(video1);
return;
}
if(status & PS_HEADER_PACK){
ps_clear_pack_list(header);
header = NULL;
header_tail = NULL;
}
current = video1;
if(header){
ps_set_pack_list_scr(header, ps_get_system_clock_reference(current)-ps_get_pack_list_scr_length(header));
current = header->data;
}
if( ps_find_system_header(current) ){
if(system){
ps_clear_pack(system);
free(system);
system = NULL;
}
}
if(system){
ps_set_system_clock_reference(system, ps_get_system_clock_reference(current)-ps_get_pack_scr_length(system));
ps_write_pack(system, file, &audio_stream);
ps_clear_pack(system);
free(system);
}
ps_initialize_video_packet(current, stream_id);
ps_write_pack_list(header, file, &audio_stream);
ps_clear_pack_list(header);
ps_write_pack(video1, file, &audio_stream);
ps_clear_pack(video1);
free(video1);
video1 = video2;
ps_write_pack_list(other, file, &audio_stream);
if(! bs_next_packet_prefix(bs) ){
ps_clear_pack_list(other);
ps_write_pack(video1, file, &audio_stream);
ps_clear_pack(video1);
free(video1);
fclose(file);
return;
}
if( bs_read_bits(bs, 32) == 0x000001ba ){
current = (PS_PACK *)calloc(1, sizeof(PS_PACK));
}else{
current = NULL;
}
while(current){
if(((MPEG2EDIT *)mpeg2edit)->callback(out_path, ps_get_current_percent(&opt)) != VF_OK){
ps_clear_pack_list(other);
ps_clear_pack(video1);
free(video1);
fclose(file);
return;
}
ps_read_pack(bs, current);
ps_set_pack_scr_length(previous, ps_get_system_clock_reference(current)-ps_get_system_clock_reference(previous));
previous = current;
if(ps_find_stream(current, stream_id)){
video2 = current;
status = ps_proc_video(video1, video2, &opt);
if(status & PS_OUTPUT_PACK){
ps_write_pack(video1, file, &audio_stream);
ps_clear_pack(video1);
free(video1);
ps_write_pack_list(other, file, &audio_stream);
ps_clear_pack_list(other);
other = NULL;
other_tail = NULL;
}else{
goto PS_EDIT_3RD_STEP;
}
video1 = video2;
}else{
if(ps_check_pack_chain(other_tail, current)){
other_tail = ps_add_pack_list(other_tail, current);
}else{
ps_clear_pack_list(other);
other = ps_add_pack_list(NULL, current);
other_tail = other;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -