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

📄 mpeg2edit.c

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

	return r;
}

static void delete_block(BLOCK *block)
{
	if(block){
		if(block->data){
			free(block->data);
			block->data = 0;
		}
		block->length = 0;
		free(block);
	}
}

static int find_block(BLOCK *current, BLOCK *next, int offset, BLOCK *pattern)
{
	int r;
	int i;

	r = offset;

	while(r < current->length){
		for(i=0;i<pattern->length;i++){
			if(r+i<current->length){
				if(current->data[r+i] == pattern->data[i]){
					continue;
				}else{
					break;
				}
			}else if(next != NULL){
				if(next->data[r-current->length+i] == pattern->data[i]){
					continue;
				}else{
					break;
				}
			}else{
				return -1;
			}
		}
		if(i == pattern->length){
			return r;
		}
		r += 1;
	}

	return -1;
}

static unsigned char get_byte_block(BLOCK *current, BLOCK *next, int offset)
{
	if(current == NULL){
		return 0;
	}

	if(offset < current->length){
		return current->data[offset];
	}else if( (next != NULL) && (offset-current->length < next->length) ){
		return next->data[offset-current->length];
	}

	return 0;
}

static void set_byte_block(BLOCK *current, BLOCK *next, int offset, unsigned char data)
{
	if(current == NULL){
		return;
	}

	if(offset < current->length){
		current->data[offset] = data;
	}else if( (next != NULL) && (offset-current->length < next->length) ){
		next->data[offset-current->length] = data;
	}
}

/*-----------------------------------------------------------------*/
static int subtract_temporal_reference(int current, int previous)
{
	if( (previous & 0x0200) && ((current & 0x03fe) == 0) ){
		current |= 0x0400;
	}

	return current - previous;
}

/*-----------------------------------------------------------------*/
static int check_ts(BITSTREAM *in)
{
	int i,n;
	int o,p,d;
	int count[376];
	int max, total;
	unsigned char buffer[460224];

	n = bs_read(in, buffer, sizeof(buffer));
	bs_seek(in, SEEK_SET, 0);

	o = 0;
	for(i=0;i<n;i++){
		if(buffer[i] == 0x47){
			o = i;
			break;
		}
	}

	if(o > 188){
		return 0;
	}
	p = o;
	total = 0;
	memset(count, 0, sizeof(count));
	for(;i<n;i++){
		if(buffer[i] == 0x47){
			d = i-p;
			if(d >= sizeof(count)/sizeof(int)){
				return 0;
			}
			count[d] += 1;
			total += 1;
			p = i;
		}
	}

	max = 0;
	for(i=0;i<sizeof(count)/sizeof(int);i++){
		if(max < count[i]){
			max = count[i];
		}
	}

	if(max > total/2){
		return 1;
	}

	return 0;
}

/*-----------------------------------------------------------------*/
static int es_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 = es_edit;
	mpeg2edit->close = es_close;
	
	return 1;
}

static void es_edit(void *mpeg2edit, char *out_path, __int64 in, __int64 out)
{
	int current_temporal_reference;
	int previous_temporal_reference;

	int current_percent;

	__int64 input_field_count;
	__int64 output_field_count;

	int closed_gop;
	int broken_link;
	int fps;

	__int64 n;

	ES_SEQUENCE_HEADER seq;
	ES_GOP_HEADER gop;
	ES_FRAME frm;

	BITSTREAM *bs;

	FILE *file;

	bs = (BITSTREAM *)((MPEG2EDIT *)mpeg2edit)->stream;

	bs_seek(bs, 0, SEEK_SET);

	current_temporal_reference = 0;
	previous_temporal_reference = 0;

	input_field_count = 0;

	memset(&seq, 0, sizeof(seq));
	memset(&gop, 0, sizeof(gop));
	memset(&frm, 0, sizeof(frm));

	closed_gop = 0;
	broken_link = 0;
	
	/* 1st step - search stream head I picture */
	while(bs_next_packet_prefix(bs)){
		switch(bs_read_bits(bs, 32)){
		case 0x000001b3:
			es_clear_sequence_header(&seq);
			es_read_sequence_header(bs, &seq);
			break;
		case 0x000001b8:
			es_clear_gop_header(&gop);
			es_read_gop_header(bs, &gop);
			current_temporal_reference = 0;
			previous_temporal_reference = 0;
			closed_gop = es_get_closed_gop(&gop);
			break;
		case 0x00000100:
			es_clear_frame(&frm);
			es_read_frame(bs, &frm);
			if(es_get_coding_type(&frm) == 1){
				if(closed_gop == 0){
					broken_link = 1;
				}
				if(seq.length){
					goto ES_EDIT_2ND_STEP;
				}
			}
			break;
		default:
			bs_erase_bits(bs, 32);
		}
	}

	es_clear_sequence_header(&seq);
	es_clear_gop_header(&gop);
	es_clear_frame(&frm);
	
	return;

ES_EDIT_2ND_STEP: /* search in point */

	if( in == 0 ){
		goto ES_EDIT_3RD_STEP;
	}

	previous_temporal_reference = es_get_temporal_reference(&frm);
	if( closed_gop && (in <= subtract_temporal_reference(previous_temporal_reference, 0)) ){
		goto ES_EDIT_3RD_STEP;
	}
	input_field_count += es_get_field_count(&frm);

	while(bs_next_packet_prefix(bs)){
		
		current_percent = (int)(input_field_count * 50 / out);
		if(((MPEG2EDIT *)mpeg2edit)->callback(out_path, current_percent) != VF_OK){
			es_clear_sequence_header(&seq);
			es_clear_gop_header(&gop);
			es_clear_frame(&frm);
			
			return;
		}
		
		switch(bs_read_bits(bs, 32)){
		case 0x000001b3:
			es_clear_sequence_header(&seq);
			es_read_sequence_header(bs, &seq);
			break;
		case 0x000001b8:
			es_clear_gop_header(&gop);
			es_read_gop_header(bs, &gop);
			closed_gop = es_get_closed_gop(&gop);
			broken_link = es_get_broken_link(&gop);
			current_temporal_reference = 0;
			previous_temporal_reference = 0;
			break;
		case 0x00000100:
			es_clear_frame(&frm);
			es_read_frame(bs, &frm);
			switch(es_get_coding_type(&frm)){
			case 1:
				if(broken_link == 1){
					broken_link = 2;
					current_temporal_reference = 0;
				}else{
					broken_link = 0;
					current_temporal_reference = es_get_temporal_reference(&frm);
				}
				if(closed_gop == 1){
					closed_gop = 2;
				}else{
					closed_gop = 0;
				}
				n = (input_field_count+1)/2;
				n += subtract_temporal_reference(current_temporal_reference, previous_temporal_reference);
				if( n >= in ){
					goto ES_EDIT_3RD_STEP;
				}
				previous_temporal_reference = es_get_temporal_reference(&frm);
				input_field_count += es_get_field_count(&frm);
				break;
			case 2:
				broken_link = 0;
				closed_gop = 0;
				previous_temporal_reference = es_get_temporal_reference(&frm);
				input_field_count += es_get_field_count(&frm);
				break;
			case 3:
				if(broken_link == 0){
					input_field_count += es_get_field_count(&frm);
				}
			}
			break;
		default:
			bs_erase_bits(bs, 32);
		}
	}

	es_clear_sequence_header(&seq);
	es_clear_gop_header(&gop);
	es_clear_frame(&frm);
	
	return;

ES_EDIT_3RD_STEP: /* output data to file */

	output_field_count = 0;

	fps = es_get_fps(&seq);
	es_set_timecode(&gop, 0, fps);
	es_set_broken_link(&gop, 0);

	file = fopen(out_path, "wb");
	if(file == NULL){
		es_clear_sequence_header(&seq);
		es_clear_gop_header(&gop);
		es_clear_frame(&frm);
		return;
	}

	es_write_sequence_header(&seq, file);
	es_write_gop_header(&gop, file);

	if(closed_gop){
		current_temporal_reference = es_get_temporal_reference(&frm);
		n = (input_field_count + 1) / 2;
		n += subtract_temporal_reference(current_temporal_reference, previous_temporal_reference);
		current_temporal_reference -= (n-in);
		es_set_temporal_reference(&frm, current_temporal_reference);
		previous_temporal_reference = current_temporal_reference;
	}else{
		previous_temporal_reference = es_get_temporal_reference(&frm);
		es_set_temporal_reference(&frm, 0);
	}
	
	n = es_get_field_count(&frm);
	input_field_count += n;
	output_field_count += n;

	es_write_frame(&frm, file);

	while(bs_next_packet_prefix(bs)){
		
		current_percent = (int)(input_field_count * 50 / out);
		if(((MPEG2EDIT *)mpeg2edit)->callback(out_path, current_percent) != VF_OK){
			es_clear_sequence_header(&seq);
			es_clear_gop_header(&gop);
			es_clear_frame(&frm);
			
			return;
		}
		
		switch(bs_read_bits(bs, 32)){
		case 0x000001b3:
			if( (input_field_count+1)/2 >= out ){
				goto ES_EDIT_4TH_STEP;
			}
			es_clear_sequence_header(&seq);
			es_read_sequence_header(bs, &seq);
			es_write_sequence_header(&seq, file);
			break;
		case 0x000001b8:
			if( (input_field_count+1)/2 >= out ){
				goto ES_EDIT_4TH_STEP;
			}
			es_clear_gop_header(&gop);
			es_read_gop_header(bs, &gop);
			
			closed_gop = es_get_closed_gop(&gop);
			broken_link = es_get_broken_link(&gop);
			
			current_temporal_reference = 0;
			previous_temporal_reference = 0;
			
			es_set_broken_link(&gop, 0);
			es_set_timecode(&gop, (output_field_count+1)/2, fps);
			es_write_gop_header(&gop, file);
			
			break;
		case 0x00000100:
			es_clear_frame(&frm);
			es_read_frame(bs, &frm);
			
			switch(es_get_coding_type(&frm)){
			case 1:
				if( (input_field_count+1)/2 >= out ){
					goto ES_EDIT_4TH_STEP;
				}
				
				if(broken_link == 1){
					broken_link = 2;
					previous_temporal_reference = es_get_temporal_reference(&frm);
				}else{
					broken_link = 0;
				}
				
				current_temporal_reference = es_get_temporal_reference(&frm);
				current_temporal_reference -= previous_temporal_reference;
				es_set_temporal_reference(&frm, current_temporal_reference);
				
				es_write_frame(&frm, file);
				
				n = es_get_field_count(&frm);
				input_field_count += n;
				output_field_count += n;
				
				break;
			case 2:
				if( (input_field_count+1)/2 >= out ){
					goto ES_EDIT_4TH_STEP;
				}

				broken_link = 0;

				current_temporal_reference = es_get_temporal_reference(&frm);
				current_temporal_reference -= previous_temporal_reference;
				es_set_temporal_reference(&frm, current_temporal_reference);

				es_write_frame(&frm, file);

				n = es_get_field_count(&frm);
				input_field_count += n;
				output_field_count += n;

				break;
			case 3:
				n = es_get_field_count(&frm);
				
				if(broken_link == 0){
					input_field_count += n;
				}

				current_temporal_reference = es_get_temporal_reference(&frm);
				if(current_temporal_reference < previous_temporal_reference){
					es_padding_frame(&frm);
				}else{
					current_temporal_reference -= previous_temporal_reference;
					es_set_temporal_reference(&frm, current_temporal_reference);
					output_field_count += n;
				}

				es_write_frame(&frm, file);
			}
			break;
		default:
			bs_erase_bits(bs, 32);
		}
	}

ES_EDIT_4TH_STEP:

	es_write_sequence_end_code(file);

	es_clear_sequence_header(&seq);
	es_clear_gop_header(&gop);
	es_clear_frame(&frm);
	
	fclose(file);
	
	((MPEG2EDIT *)mpeg2edit)->callback(out_path, 100);
	
	return;
	
}

static void es_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 int es_read_sequence_header(BITSTREAM *in, ES_SEQUENCE_HEADER *out)
{
	if(bs_read_bits(in, 32) != 0x000001b3){
		return 0;
	}
	
	out->head = read_list(in, 512, es_judge_read_sequence_header_end);
	out->length = count_list_size(out->head);
	
	return out->length;
}

static int es_read_gop_header(BITSTREAM *in, ES_GOP_HEADER *out)
{
	if(bs_read_bits(in, 32) != 0x000001b8){
		return 0;
	}
	
	out->head = read_list(in, 128, es_judge_read_gop_header_end);
	out->length = count_list_size(out->head);
	
	return out->length;
}

static int es_read_picture(BITSTREAM *in, ES_PICTURE *out)
{
	if(bs_read_bits(in, 32) != 0x00000100){
		return 0;
	}
	
	out->head = read_list(in, 8192, es_judge_read_picture_end);
	out->length = count_list_size(out->head);

	return out->length;
}

static int es_read_frame(BITSTREAM *in, ES_FRAME *out)
{
	int r;

	r = es_read_picture(in, &(out->fst));

	if(es_get_picture_field_count(&(out->fst)) == 1){
		r += es_read_picture(in, &(out->snd));
	}

	return r;
}

static int es_judge_read_sequence_header_end(int code)
{
	if(code == 0x00000100){ /* picture_start_code */
		return 1;
	}else if(code == 0x000001b8){ /* gop_start_code */
		return 1;
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -