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

📄 picture.c

📁 由bmp生成mpeg2 的I_frame 数据
💻 C
字号:
/*******************************************************************
                picture decoding (reconstract) module
 *******************************************************************/

#define PICTURE_C
#include "picture.h"

/* in block_mmx.asm */
extern void __stdcall copy_i_block_to_frame_mmx(short *in, unsigned char *out, int step);
extern void __stdcall add_diff_to_frame_mmx(short *in, unsigned char *out, int step);


int decode_picture(VIDEO_STREAM *in, MC_BUFFER *out, DECODE_PICTURE_PARAMETER *prm);

void add_block_data_to_frame(short *in, FRAME *out, READ_BLOCK_OPTION *opt, int x, int y, int block_number);
void add_block_data_to_frame_mmx(short *in, FRAME *out, READ_BLOCK_OPTION *opt, int x, int y, int block_number);

static void check_motion_vector(MC_PARAMETER *prm, int x, int y, int width, int height);
static void black_mb(FRAME *out, int x, int y, int chroma_format, int picture_structure);
static void rewind_video_stream(VIDEO_STREAM *in, int slice_vertical_pos);

int decode_picture(VIDEO_STREAM *in, MC_BUFFER *out, DECODE_PICTURE_PARAMETER *prm)
{
	SLICE_HEADER sh;
	MACROBLOCK   mb;

	__declspec(align(16)) short block[64];

	int x, y, address, inc, width, height, max, pos;
	int i;

	address = 0;
	width = out->current->width;
	height = out->current->height;
	max = width * height / 16;
	if(prm->mc_parameter.picture_structure != 3){
		max /= 2;
	}

	while(vs_next_start_code(in)){
		
		if(!read_slice_header(in, &sh, &(prm->slice_option))){
			/*
			 * error concealment -
			 *   copy MB from forward refernce frame until next picture
			 */
			
			if(address){
				/* back one block */
				address -= 16;
			}
			
			macroblock_to_error_concealment_mc_parameter(&mb, &(prm->mc_parameter));
			
			while(address<max){
				x = address % width;
				y = address / width * 16;
				if(prm->mc_parameter.picture_structure != 3){
					y *= 2;
				}
				if(prm->mc_parameter.macroblock_motion_forward && out->forward == NULL){
				/* no referrence frame */
					black_mb(out->current, x, y, prm->mc_parameter.chroma_format, prm->mc_parameter.picture_structure);
				}else{ /* has referrence frame */
					check_motion_vector(&(prm->mc_parameter), x, y, width, height);
					mc(out, &(prm->mc_parameter), x, y);
				}					
				address += 16;
			}
			
			/* error recovery hack */
			vs_rewind(in);
			
			return 0;
		}

		slice_header_to_read_block_option(&sh, &(prm->block_option));

		reset_motion_vector_predictor(&mb);

		inc = get_macroblock_address_increment(in);
		
		/* check slice position */
		pos = (sh.slice_vertical_position-1)*width + (inc-1)*16;
		
		if( address == pos ){
			inc = 1;
		}else if( (pos < address) && (address < pos+width) ){
			inc = 1;
			address = pos;
		}else{
			/*
			 * error concealment - 
			 *   copy MB from forward reference frame until current slice
			 */
			macroblock_to_error_concealment_mc_parameter(&mb, &(prm->mc_parameter));

			if( (pos > max) || (pos < address) ){
				pos = max;
			}

			if(address){
				/* back one block */
				address -= 16;
			}
			
			while(address < pos){
				x = address % width;
				y = address / width * 16;
				if(prm->mc_parameter.picture_structure != 3){
					y *= 2;
				}
				if(prm->mc_parameter.macroblock_motion_forward && out->forward == NULL){
					/* no referrence frame */
					black_mb(out->current, x, y, prm->mc_parameter.chroma_format, prm->mc_parameter.picture_structure);
				}else{ /* has referrence frame */
					check_motion_vector(&(prm->mc_parameter), x, y, width, height);
					mc(out, &(prm->mc_parameter), x, y);
				}
				address += 16;
			}

			if(pos == max){
				/* error recovery hack */
				vs_rewind(in);
				
				return 0;
			}

			inc = 1;
		}

		do{
			x = address % width;
			y = address / width * 16;
			if(prm->macroblock_option.picture_structure != 3){
				y *= 2;
			}

			if(!read_macroblock(in, &mb, &(prm->macroblock_option))){
				break;
			}

			if(mb.macroblock_intra == 0){
				macroblock_to_mc_parameter(&mb, &(prm->mc_parameter));
				check_motion_vector(&(prm->mc_parameter), x, y, width, height);
				mc(out, &(prm->mc_parameter), x, y);
			}

			macroblock_to_read_block_option(&mb, &(prm->block_option));
			for(i=0;i<mb.block_count;i++){
				if(mb.read_block[i](in, block, &(prm->block_option))){
					prm->idct_func(block);
					prm->add_block_func(block, out->current, &(prm->block_option), x, y, i);
				}
			}
			address += 16;
			
			if(address >= max){ /* all macroblocks have decoded */
				return 1;
			}
			
			inc = get_macroblock_address_increment(in);
			if(inc == 0){ /* goto next slice */
				break;
			}

			if(inc != 1){ /* skipped macroblock */
				reset_dc_dct_predictor(&(prm->block_option));
				if(prm->macroblock_option.picture_coding_type == 2){
					reset_motion_vector_predictor(&mb);
					macroblock_to_mc_parameter(&mb, &(prm->mc_parameter));
				}
				if(prm->mc_parameter.picture_structure == 3){
					prm->mc_parameter.prediction_type = PREDICTION_TYPE_FRAME_BASED;
				}else{
					prm->mc_parameter.prediction_type = PREDICTION_TYPE_FIELD_BASED;
					prm->mc_parameter.motion_vertical_field_select[0][0] = (prm->mc_parameter.picture_structure == 2);
					prm->mc_parameter.motion_vertical_field_select[0][1] = (prm->mc_parameter.picture_structure == 2);
				}
			}

			for(i=0;i<inc-1;i++){

				x = address % width;
				y = address / width * 16;
				if(prm->mc_parameter.picture_structure != 3){
					y *= 2;
				}
				mc(out, &(prm->mc_parameter), x, y);

				address += 16;
			}

		}while(1);
	}

	return 1;
}

static const int cc_table[] = {
	0, 0, 0, 0, 1, 2, 1, 2, 1, 2, 1, 2,
};

static const int x_offset[12] = {
	0, 8, 0, 8, 0, 0, 0, 0, 8, 8, 8, 8,
};

static const int y_offset[12][4][2] = {
	{/* block_number - 0 */
		{/* dummy */
			0, 0,
		},
		{/* picture_structure - 1 */
			0, 0,
		},
		{/* picture_structure - 2 */
			1, 1,
		},
		{/* picture_structure - 3 */
			0, 0,
		},
	},
	{/* block_number - 1 */
		{/* dummy */
			0, 0,
		},
		{/* picture_structure - 1 */
			0, 0,
		},
		{/* picture_structure - 2 */
			1, 1,
		},
		{/* picture_structure - 3 */
			0, 0,
		},
	},
	{/* block_number - 2 */
		{/* dummy */
			0, 0,
		},
		{/* picture_structure - 1 */
			16, 16,
		},
		{/* picture_structure - 2 */
			17, 17,
		},
		{/* picture_structure - 3 */
			8, 1,
		},
	},
	{/* block_number - 3 */
		{/* dummy */
			0, 0,
		},
		{/* picture_structure - 1 */
			16, 16,
		},
		{/* picture_structure - 2 */
			17, 17,
		},
		{/* picture_structure - 3 */
			8, 1,
		},
	},
	{/* block_number - 4 */
		{/* dummy */
			0, 0,
		},
		{/* picture_structure - 1 */
			0, 0,
		},
		{/* picture_structure - 2 */
			1, 1,
		},
		{/* picture_structure - 3 */
			0, 0,
		},
	},
	{/* block_number - 5 */
		{/* dummy */
			0, 0,
		},
		{/* picture_structure - 1 */
			0, 0,
		},
		{/* picture_structure - 2 */
			1, 1,
		},
		{/* picture_structure - 3 */
			0, 0,
		},
	},
	{/* block_number - 6 */
		{/* dummy */
			0, 0,
		},
		{/* picture_structure - 1 */
			16, 16,
		},
		{/* picture_structure - 2 */
			17, 17,
		},
		{/* picture_structure - 3 */
			8, 1,
		},
	},
	{/* block_number - 7 */
		{/* dummy */
			0, 0,
		},
		{/* picture_structure - 1 */
			16, 16,
		},
		{/* picture_structure - 2 */
			17, 17,
		},
		{/* picture_structure - 3 */
			8, 1,
		},
	},
	{/* block_number - 8 */
		{/* dummy */
			0, 0,
		},
		{/* picture_structure - 1 */
			0, 0,
		},
		{/* picture_structure - 2 */
			1, 1,
		},
		{/* picture_structure - 3 */
			0, 0,
		},
	},
	{/* block_number - 9 */
		{/* dummy */
			0, 0,
		},
		{/* picture_structure - 1 */
			0, 0,
		},
		{/* picture_structure - 2 */
			1, 1,
		},
		{/* picture_structure - 3 */
			0, 0,
		},
	},
	{/* block_number - 10 */
		{/* dummy */
			0, 0,
		},
		{/* picture_structure - 1 */
			16, 16,
		},
		{/* picture_structure - 2 */
			17, 17,
		},
		{/* picture_structure - 3 */
			8, 1,
		},
	},
	{/* block_number - 11 */
		{/* dummy */
			0, 0,
		},
		{/* picture_structure - 1 */
			16, 16,
		},
		{/* picture_structure - 2 */
			17, 17,
		},
		{/* picture_structure - 3 */
			8, 1,
		},
	},
};

static const int y_shift[3][4] = {
	{/* cc == 0, y */
		0, 0, 0, 0,
	},
	{/* cc == 1, u */
		0, 1, 0, 0,
	},
	{/* cc == 2, v */
		0, 1, 0, 0,
	},
};

static const int x_shift[3][4] = {
	{/* cc == 0, y */
		0, 0, 0, 0,
	},
	{/* cc == 1, u */
		0, 1, 1, 0,
	},
	{/* cc == 2, v */
		0, 1, 1, 0,
	}
};

static const int step_shift[3][4][4][2] = {
	{/* cc == 0 */
		{/* dummy */
			{/* dummy */
				0, 0,
			},
			{/* chroma_format == 1 */
				0, 0,
			},
			{/* chroma_format == 2 */
				0, 0,
			},
			{/* chroma_format == 3 */
				0, 0,
			},
		},
		{/* picture_structure == 1 */
			{/* dummy */
				0, 0,
			},
			{/* chroma_format == 1 */
				1, 1,
			},
			{/* chroma_format == 2 */
				1, 1,
			},
			{/* chroma_format == 3 */
				1, 1,
			},
		},
		{/* picture_structure == 2 */
			{/* dummy */
				0, 0,
			},
			{/* chroma_format == 1 */
				1, 1,
			},
			{/* chroma_format == 2 */
				1, 1,
			},
			{/* chroma_format == 3 */
				1, 1,
			},
		},
		{/* picture_structure == 3 */
			{/* dummy */
				0, 0,
			},
			{/* chroma_format == 1 */
				0, 1,
			},
			{/* chroma_format == 2 */
				0, 1,
			},
			{/* chroma_format == 3 */
				0, 1,
			},
		},
	},
	{/* cc == 1 */
		{/* dummy */
			{/* dummy */
				0, 0,
			},
			{/* chroma_format == 1 */
				0, 0,
			},
			{/* chroma_format == 2 */
				0, 0,
			},
			{/* chroma_format == 3 */
				0, 0,
			},
		},
		{/* picture_structure == 1 */
			{/* dummy */
				0, 0,
			},
			{/* chroma_format == 1 */
				1, 1,
			},
			{/* chroma_format == 2 */
				1, 1,
			},
			{/* chroma_format == 3 */
				1, 1,
			},
		},
		{/* picture_structure == 2 */
			{/* dummy */
				0, 0,
			},
			{/* chroma_format == 1 */
				1, 1,
			},
			{/* chroma_format == 2 */
				1, 1,
			},
			{/* chroma_format == 3 */
				1, 1,
			},
		},
		{/* picture_structure == 3 */
			{/* dummy */
				0, 0,
			},
			{/* chroma_format == 1 */
				0, 0,
			},
			{/* chroma_format == 2 */
				0, 1,
			},
			{/* chroma_format == 3 */
				0, 1,
			},
		},
	},
	{/* cc == 2 */
		{/* dummy */
			{/* dummy */
				0, 0,
			},
			{/* chroma_format == 1 */
				0, 0,
			},
			{/* chroma_format == 2 */
				0, 0,
			},
			{/* chroma_format == 3 */
				0, 0,
			},
		},
		{/* picture_structure == 1 */
			{/* dummy */
				0, 0,
			},
			{/* chroma_format == 1 */
				1, 1,
			},
			{/* chroma_format == 2 */
				1, 1,
			},
			{/* chroma_format == 3 */
				1, 1,
			},
		},
		{/* picture_structure == 2 */
			{/* dummy */
				0, 0,
			},
			{/* chroma_format == 1 */
				1, 1,
			},
			{/* chroma_format == 2 */
				1, 1,
			},
			{/* chroma_format == 3 */
				1, 1,
			},
		},
		{/* picture_structure == 3 */
			{/* dummy */
				0, 0,
			},
			{/* chroma_format == 1 */
				0, 0,
			},
			{/* chroma_format == 2 */
				0, 1,
			},
			{/* chroma_format == 3 */
				0, 1,
			},
		},
	},
};

void add_block_data_to_frame(short *in, FRAME *out, READ_BLOCK_OPTION *opt, int x, int y, int block_number)
{
	int i,j;
	int step, cc;
	unsigned char *p;
	
	cc = cc_table[block_number];
	
	switch(cc){
	case 0:
		p = out->y;
		break;
	case 1:
		p = out->u;
		break;
	case 2:
		p = out->v;
		break;
	default:
		return;    
	};

	x >>= x_shift[cc][opt->chroma_format];
	y >>= y_shift[cc][opt->chroma_format];
	step = out->width << step_shift[cc][opt->picture_structure][opt->chroma_format][opt->dct_type];
	p += (y + y_offset[block_number][opt->picture_structure][opt->dct_type]) * out->width;
	p += x + x_offset[block_number];
	
	if(opt->macroblock_intra){
		for(i=0;i<8;i++){
			for(j=0;j<8;j++){
				p[j] = uchar_clip_table[UCHAR_CLIP_TABLE_OFFSET+in[j]];
			}
			p += step;
			in += 8;
		}
	}else{
		for(i=0;i<8;i++){
			for(j=0;j<8;j++){
				p[j] = uchar_clip_table[UCHAR_CLIP_TABLE_OFFSET+p[j]+in[j]];
			}
			p += step;
			in += 8;
		}
	}
}

typedef void ( __stdcall *ADD_BLOCK_CORE)(short *, unsigned char *, int);

void add_block_data_to_frame_mmx(short *in, FRAME *out, READ_BLOCK_OPTION *opt, int x, int y, int block_number)
{
	int step, cc;
	unsigned char *p;

	static const ADD_BLOCK_CORE table[2] = {
		add_diff_to_frame_mmx, copy_i_block_to_frame_mmx,
	};
	
	cc = cc_table[block_number];
	
	switch(cc){
	case 0:
		p = out->y;
		break;
	case 1:
		p = out->u;
		break;
	case 2:
		p = out->v;
		break;
	default:
		return;    
	};

	x >>= x_shift[cc][opt->chroma_format];
	y >>= y_shift[cc][opt->chroma_format];
	step = out->width << step_shift[cc][opt->picture_structure][opt->chroma_format][opt->dct_type];
	p += (y + y_offset[block_number][opt->picture_structure][opt->dct_type]) * out->width;
	p += x + x_offset[block_number];
	
	table[opt->macroblock_intra](in, p, step);
}

static void check_motion_vector(MC_PARAMETER *prm, int x, int y, int width, int height)
{
	int r,s;

	for(r=0;r<2;r++){
		for(s=0;s<2;s++){
			if(prm->PMV[r][s][0] < -2 * x){
				prm->PMV[r][s][0] = -2 * x;
			}else if(prm->PMV[r][s][0] > (width-x-16)*2){
				prm->PMV[r][s][0] = (width-x-16)*2;
			}
			if(prm->PMV[r][s][1] < -2 * y){
				prm->PMV[r][s][1] = - 2 * y;
			}else if(prm->PMV[r][s][1] > (height-y-16)*2){
				prm->PMV[r][s][1] = (height-y-16)*2;
			}
		}
		if(prm->DMV[r][0] < -2 * x){
			prm->DMV[r][0] = -2 * x;
		}else if(prm->DMV[r][0] > (width-x-16)*2){
			prm->DMV[r][0] = (width-x-16)*2;
		}
		if(prm->DMV[r][1] < -y){
			prm->DMV[r][1] = -y;
		}else if(prm->DMV[r][1] > (height-y-16)){
			prm->DMV[r][1] = (height-y-16);
		}
	}
}

static void black_mb(FRAME *out, int x, int y, int chroma_format, int picture_structure)
{
	int i,j;
	int step, offset;
	int bx,by;

	unsigned char *p;

	step = out->width;
	offset = 0;
	if(picture_structure != 3){
		step += out->width;
		if(picture_structure == 2){
			offset = out->width;
		}
	}

	/* for Y */
	p = out->y + (y * out->width + x) + offset;

	for(i=0;i<16;i++){
		for(j=0;j<16;j++){
			p[j] = 16;
		}
		p += step;
	}
	
	switch(chroma_format){
	case 1: /* 420 */
		bx = 8;
		by = 8;
		y >>= 1;
		x >>= 1;
		break;
	case 2: /* 422 */
		bx = 8;
		by = 16;
		x >>= 1;
		break;
	case 3: /* 444 */
	default:
		bx = 16;
		by = 16;
		break;
	}

	/* for Cb */
	p = out->u + (y * out->width + x) + offset;
	for(i=0;i<by;i++){
		for(j=0;j<bx;j++){
			p[j] = 128;
		}
		p += step;
	}

	/* for Cr */
	p = out->v + (y * out->width + x) + offset;
	for(i=0;i<by;i++){
		for(j=0;j<bx;j++){
			p[j] = 128;
		}
		p += step;
	}
}

⌨️ 快捷键说明

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