📄 mpeg2edit.c
字号:
}
}
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_proc_video(video1, NULL, &opt);
ps_write_pack(video1, file, &audio_stream);
ps_write_pack_list(other, file, &audio_stream);
video2 = NULL;
PS_EDIT_3RD_STEP:
ps_clear_pack_list(other);
if(video1){
ps_clear_pack(video1);
free(video1);
}
if(video2){
ps_clear_pack(video2);
free(video2);
}
ps_write_program_end_code(file);
fclose(file);
if(!ps_check_empty_stream_id_list(&audio_stream)){
ps_trim_audio_packet(out_path, &audio_stream);
}
((MPEG2EDIT *)mpeg2edit)->callback(out_path, 100);
return;
}
static void ps_close(void *mpeg2edit)
{
MPEG2EDIT *p;
BITSTREAM *bs;
p = (MPEG2EDIT *)mpeg2edit;
bs = (BITSTREAM *)p->stream;
bs_close(bs);
p->stream = NULL;
p->edit = dummy_edit;
p->close = dummy_close;
}
static void ps_write_program_end_code(FILE *out)
{
unsigned char pattern[4] = {
0, 0, 1, 0xb9,
};
fwrite(pattern, 1, 4, out);
}
static int ps_read_pack(BITSTREAM *in, PS_PACK *out)
{
int r;
if(bs_read_bits(in, 32) != 0x000001ba){ /* pack_start_code */
return 0;
}
out->pack_header = read_list(in, 512, ps_judge_read_pack_header_end);
out->pes_packet = ps_read_pes_packet(in);
out->scr_length = 0;
r = count_list_size(out->pack_header);
r += count_list_size(out->pes_packet);
return r;
}
static void ps_write_pack(PS_PACK *in, FILE *out, STREAM_ID_LIST *audio_stream)
{
__int64 offset;
if(in == NULL){
return;
}
fflush(out);
offset = _telli64(_fileno(out));
ps_check_audio_stream(in, offset, audio_stream);
fwrite_list(in->pack_header, out);
fwrite_list(in->pes_packet, out);
}
static void ps_clear_pack(PS_PACK *pack)
{
if(pack == NULL){
return;
}
clear_list(pack->pack_header);
pack->pack_header = NULL;
clear_list(pack->pes_packet);
pack->pes_packet = NULL;
}
static void ps_copy_system_header_pack(PS_PACK *in, PS_PACK *out)
{
int length;
LIST_ELEMENT *packet;
if( (in == NULL) || (out == NULL) ){
return;
}
out->pack_header = copy_list(in->pack_header);
out->pes_packet = copy_list(in->pes_packet);
packet = out->pes_packet;
while(packet){
length = packet->length-6;
packet->data[0] = 0;
packet->data[1] = 0;
packet->data[2] = 1;
packet->data[3] = 0xbe;
packet->data[4] = (unsigned char)((length >> 8) & 0xff);
packet->data[5] = (unsigned char)(length & 0xff);
memset(packet->data+6, 0xff, length);
packet = (LIST_ELEMENT *)packet->next;
}
}
static int ps_find_system_header(PS_PACK *pack)
{
unsigned char pattern[4] = {
0, 0, 1, 0xbb,
};
if(pack == NULL){
return 0;
}
if(find_list(pack->pack_header, 0, pattern, 4) < 0){
return 0;
}
return 1;
}
static int ps_get_video_stream_id(PS_PACK *pack)
{
LIST_ELEMENT *current;
if(pack == NULL){
return 0;
}
current = pack->pes_packet;
while(current){
if( (current->data[3] & 0xf0) == 0xe0 ){
return current->data[3];
}
current = (LIST_ELEMENT *)current->next;
}
return 0;
}
static int ps_find_stream(PS_PACK *pack, int stream_id)
{
LIST_ELEMENT *current;
if(pack == NULL){
return 0;
}
current = pack->pes_packet;
while(current){
if(current->data[3] == stream_id){
return 1;
}
current = (LIST_ELEMENT *)current->next;
}
return 0;
}
static __int64 ps_get_system_clock_reference(PS_PACK *pack)
{
__int64 base,ext;
if(pack == NULL){
return 0;
}
if( (get_byte_list(pack->pack_header, 4) & 0xc0) == 0x40 ){ /* MPEG-2 */
base = (get_byte_list(pack->pack_header, 4) >> 3) & 7;
base <<= 2;
base += get_byte_list(pack->pack_header, 4) & 3;
base <<= 8;
base += get_byte_list(pack->pack_header, 5);
base <<= 5;
base += (get_byte_list(pack->pack_header, 6) >> 3) & 0x1f;
base <<= 2;
base += get_byte_list(pack->pack_header, 6) & 3;
base <<= 8;
base += get_byte_list(pack->pack_header, 7);
base <<= 5;
base += (get_byte_list(pack->pack_header, 8) >> 3) & 0x1f;
ext = get_byte_list(pack->pack_header, 8) & 3;
ext <<= 7;
ext += get_byte_list(pack->pack_header, 9) >> 1;
}else{ /* MPEG-1 */
base = (get_byte_list(pack->pack_header, 4) >> 1) & 7;
base <<= 8;
base += get_byte_list(pack->pack_header, 5);
base <<= 7;
base += (get_byte_list(pack->pack_header, 6) >> 1) & 0x7f;
base <<= 8;
base += get_byte_list(pack->pack_header, 7);
base <<= 7;
base += (get_byte_list(pack->pack_header, 8) >> 1) & 0x7f;
ext = 0;
}
return (base * 300) + ext;
}
static void ps_set_system_clock_reference(PS_PACK *pack, __int64 scr)
{
__int64 diff;
__int64 base;
__int64 ext;
unsigned char c4;
unsigned char c5;
unsigned char c6;
unsigned char c7;
unsigned char c8;
unsigned char c9;
LIST_ELEMENT *pes_packet;
if(pack == NULL){
return;
}
diff = scr - ps_get_system_clock_reference(pack);
base = scr / 300;
ext = scr % 300;
if( (get_byte_list(pack->pack_header, 4) & 0xc0) == 0x40 ){ /* MPEG-2 */
c4 = (unsigned char)(0x40 + (((base >> 30) & 7) << 3) + 4 + ((base >> 28) & 3));
c5 = (unsigned char)((base >> 20) & 0xff);
c6 = (unsigned char)((((base >> 15) & 0x1f) << 3) + 4 + ((base >> 13) & 3));
c7 = (unsigned char)((base >> 5) & 0xff);
c8 = (unsigned char)(((base & 0x1f) << 3) + 4 + ((ext >> 7) & 3));
c9 = (unsigned char)(((ext & 0x7f) << 1) + 1);
}else{
c4 = (unsigned char)(0x20 + (((base >> 30) & 7) << 1) + 1);
c5 = (unsigned char)((base >> 22) & 0xff);
c6 = (unsigned char)((((base >> 15) & 0x7f) << 1) + 1);
c7 = (unsigned char)((base >> 7) & 0xff);
c8 = (unsigned char)(((base & 0x7f) << 1) + 1);
c9 = get_byte_list(pack->pack_header, 9);
}
set_byte_list(pack->pack_header, 4, c4);
set_byte_list(pack->pack_header, 5, c5);
set_byte_list(pack->pack_header, 6, c6);
set_byte_list(pack->pack_header, 7, c7);
set_byte_list(pack->pack_header, 8, c8);
set_byte_list(pack->pack_header, 9, c9);
pes_packet = pack->pes_packet;
while(pes_packet){
ps_set_clock_reference_pes_packet(pes_packet, diff);
pes_packet = (LIST_ELEMENT *)pes_packet->next;
}
}
static __int64 ps_get_pack_scr_length(PS_PACK *pack)
{
if(pack == NULL){
return 0;
}
return pack->scr_length;
}
static void ps_set_pack_scr_length(PS_PACK *pack, __int64 scr_length)
{
if(pack == NULL){
return;
}
pack->scr_length = scr_length;
}
static int ps_proc_video(PS_PACK *current, PS_PACK *next, PS_PROC_VIDEO_OPTION *opt)
{
BLOCK *b1;
BLOCK *b2;
int old_offset;
int new_offset;
int code;
int r;
static unsigned char start_code[] = {
0, 0, 1,
};
static BLOCK pattern = {
start_code,
3,
};
b1 = ps_join_stream(current, opt->stream_id);
b2 = ps_join_stream(next, opt->stream_id);
old_offset = opt->offset;
if(opt->step == PS_STEP_END){
opt->output = PS_WASTE_PACK;
}
while( (new_offset = find_block(b1, b2, old_offset, &pattern)) >= 0 ){
if((new_offset+3) < b1->length){
code = b1->data[new_offset+3];
}else{
code = b2->data[new_offset+3-b1->length];
}
switch(code){
case 0x00: /* picture start code */
old_offset = ps_proc_video_picture(b1, b2, old_offset, new_offset, opt);
break;
case 0xb3: /* sequence start code */
old_offset = ps_proc_video_sequence(b1, b2, old_offset, new_offset, opt);
break;
case 0xb5:
old_offset = ps_proc_video_extension(b1, b2, old_offset, new_offset, opt);
break;
case 0xb7: /* sequence end code */
old_offset = ps_proc_video_end(b1, b2, old_offset, new_offset, opt);
break;
case 0xb8: /* gop start code */
old_offset = ps_proc_video_gop(b1, b2, old_offset, new_offset, opt);
break;
default: /* other start code */
old_offset = ps_proc_video_other(b1, b2, old_offset, new_offset+4, opt);
}
}
if(old_offset < b1->length){
old_offset = ps_proc_video_other(b1, b2, old_offset, b1->length, opt);
}
opt->offset = old_offset - b1->length;
r = PS_WASTE_PACK;
if(opt->sequence & (PS_HEADER_PACK|PS_HEADER_CHAIN_PACK)){
r |= opt->sequence;
if(opt->picture){
opt->sequence = PS_WASTE_PACK;
}else{
opt->sequence = PS_HEADER_CHAIN_PACK;
}
}
r |= opt->output;
ps_update_stream(current, opt->stream_id, b1);
ps_update_stream(next, opt->stream_id, b2);
delete_block(b1);
delete_block(b2);
if(opt->step == PS_STEP_END){
ps_terminate_video_packet(current, opt->stream_id);
}
return r;
}
static int ps_judge_read_pack_header_end(int code)
{
if(code > 0x000001bb){
return 1;
}
return 0;
}
static LIST_ELEMENT *ps_read_pes_packet(BITSTREAM *in)
{
int n,code;
int packet_length;
LIST_ELEMENT *r;
LIST_ELEMENT *current;
const int max_packet_length = 65542;
code = bs_read_bits(in, 32);
if( ((code & 0xffffff00) != 0x00000100) || ((code & 0x000000ff) < 0xbc) ){
return NULL;
}
current = new_list_element(NULL, max_packet_length);
if(current == NULL){
return NULL;
}
r = current;
do{
while(current->length < 6){
n = bs_read(in, current->data+current->length, 6-current->length);
current->length += n;
}
packet_length = (current->data[4] << 8) + current->data[5];
packet_length += 6; /* packet_prefix(3) + stream_id(1) + data_length(2) */
while(current->length < packet_length){
n = bs_read(in, current->data+current->length, packet_length-current->length);
current->length += n;
}
code = bs_read_bits(in, 32);
current->data = (unsigned char *)realloc(current->data, current->length);
if( ((code & 0xffffff00) == 0x00000100) && ((code & 0x000000ff) > 0xbb) ){
current = new_list_element(current, max_packet_length);
}else{
current = NULL;
}
}while(current);
return r;
}
static void ps_init_proc_video_option(PS_PROC_VIDEO_OPTION *opt, __int64 in, __int64 out)
{
opt->in = in;
opt->out = out;
opt->input_field = 0;
opt->output_field = 0;
opt->stream_id = 0;
opt->offset = 0;
opt->sequence = PS_WASTE_PACK;
opt->picture = 0;
opt->output = PS_WASTE_PACK;
opt->level = PS_LEVEL_SEQUENCE;
opt->step = PS_STEP_START;
opt->temporal_reference = 0;
opt->padding = 0;
opt->rate = 30;
opt->scale = 1;
opt->fps = 30;
opt->closed_gop = 0;
opt->broken_link = 0;
}
static void ps_set_stream_id_proc_video_option(PS_PROC_VIDEO_OPTION *opt, int stream_id)
{
if( (stream_id & 0xf0) == 0xe0 ){
opt->stream_id = stream_id;
}
}
static int ps_get_current_percent(PS_PROC_VIDEO_OPTION *opt)
{
__int64 r;
r = opt->input_field * 50 / opt->out;
return (int)r;
}
static PS_PACK_LIST_ELEMENT *ps_add_pack_list(PS_PACK_LIST_ELEMENT *pos, PS_PACK *data)
{
PS_PACK_LIST_ELEMENT *r;
r = (PS_PACK_LIST_ELEMENT *)calloc(1, sizeof(PS_PACK_LIST_ELEMENT));
r->data = data;
r->prev = pos;
if( pos != NULL ){
r->next = pos->next;
pos->next = r;
}
return r;
}
static void ps_write_pack_list(PS_PACK_LIST_ELEMENT *head, FILE *out, STREAM_ID_LIST *audio_stream)
{
while(head){
ps_write_pack(head->data, out, audio_stream);
head = (PS_PACK_LIST_ELEMENT *)head->next;
}
}
static void ps_clear_pack_list(PS_PACK_LIST_ELEMENT *head)
{
PS_PACK_LIST_ELEMENT *p;
while(head){
ps_clear_pack(head->data);
free(head->data);
p = (PS_PACK_LIST_ELEMENT *)head->next;
free(head);
head = p;
}
}
static int ps_check_pack_chain(PS_PACK_LIST_ELEMENT *tail, PS_PACK *next)
{
__int64 scr;
if(tail == NULL){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -