⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpeg2edit.c

📁 由bmp生成mpeg2 的I_frame 数据
💻 C
📖 第 1 页 / 共 5 页
字号:
			}
		}

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