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

📄 mp4_block.c

📁 一个的MP4解码程序.通过它可以将MP4的音频转换为yuv原始格式
💻 C
字号:


#include <math.h>
#include <stdlib.h>
#include <assert.h>

#include "mp4_vars.h"

#include "getbits.h"
#include "clearblock.h"
#include "mp4_iquant.h"
#include "mp4_predict.h"
#include "mp4_vld.h"
#include "debug.h"
#include "mp4_block.h"

/**
 *
**/

static int getDCsizeLum();
static int getDCsizeChr();
static int getDCdiff();
static void setDCscaler(int block_num);

static int getACdir();

/***/


int block(int block_num, int coded)
{
	int i;
	int dct_dc_size, dct_dc_diff;
	int intraFlag = ((mp4_state->hdr.derived_mb_type == INTRA) || 
		(mp4_state->hdr.derived_mb_type == INTRA_Q)) ? 1 : 0;
	event_t event;

	clearblock(ld->block); 

	if (intraFlag)
	{
		setDCscaler(block_num); 

		if (block_num < 4) {
			dct_dc_size = getDCsizeLum();
			if (dct_dc_size != 0) 
				dct_dc_diff = getDCdiff(dct_dc_size);
			else 
				dct_dc_diff = 0;
			if (dct_dc_size > 8)
				getbits1(); 
		}
		else {
			dct_dc_size = getDCsizeChr();
			if (dct_dc_size != 0)
				dct_dc_diff = getDCdiff(dct_dc_size);
			else 
				dct_dc_diff = 0;
			if (dct_dc_size > 8)
				getbits1(); 
		}

		ld->block[0] = (short) dct_dc_diff;

	}
	if (intraFlag)
	{

		dc_recon(block_num, &ld->block[0]);
	}

	if (coded) 
	{
		unsigned int * zigzag;

		if ((intraFlag) && (mp4_state->hdr.ac_pred_flag == 1)) {

			if (mp4_state->coeff_pred.predict_dir == TOP)
				zigzag = mp4_tables->alternate_horizontal_scan;
			else
				zigzag = mp4_tables->alternate_vertical_scan;
		}
		else {
			zigzag = mp4_tables->zig_zag_scan;
		}

		i = intraFlag ? 1 : 0;
		do 
		{
			event = vld_event(intraFlag);
			
			i+= event.run;
			ld->block[zigzag[i]] = (short) event.level;

			i++;
		} while (! event.last);
	}

	if (intraFlag)
	{
		ac_recon(block_num, &ld->block[0]);
	}

#ifdef _DEBUG_B_ACDC
	if (intraFlag)
	{
		int i;
		_Print("After AcDcRecon:\n");
		_Print("   x ");
		for (i = 1; i < 64; i++) {
			if ((i != 0) && ((i % 8) == 0))
				_Print("\n");
			_Print("%4d ", ld->block[i]);
		}
		_Print("\n");
	}
#endif // _DEBUG_ACDC

	if (mp4_state->hdr.quant_type == 0)
	{
		
		iquant(ld->block, intraFlag);
	}
	else 
	{
		_Error("Error: MPEG-2 inverse quantization NOT implemented\n");
		exit(110);
	}

#ifdef _DEBUG_B_QUANT
	{
		int i;
		_Print("After IQuant:\n");
		_Print("   x ");
		for (i = 1; i < 64; i++) {
			if ((i != 0) && ((i % 8) == 0))
				_Print("\n");
			_Print("%4d ", ld->block[i]);
		}
		_Print("\n");
	}
#endif 
	
	idct(ld->block);

	return 1;
}

/***/

int blockIntra(int block_num, int coded)
{
	int i;
	int dct_dc_size, dct_dc_diff;
	event_t event;

	clearblock(ld->block); 

	setDCscaler(block_num); 

	if (block_num < 4) {
		dct_dc_size = getDCsizeLum();
		if (dct_dc_size != 0) 
			dct_dc_diff = getDCdiff(dct_dc_size);
		else 
			dct_dc_diff = 0;
		if (dct_dc_size > 8)
			getbits1(); 
	}
	else {
		dct_dc_size = getDCsizeChr();
		if (dct_dc_size != 0)
			dct_dc_diff = getDCdiff(dct_dc_size);
		else 
			dct_dc_diff = 0;
		if (dct_dc_size > 8)
			getbits1(); 
	}

	ld->block[0] = (short) dct_dc_diff;

	dc_recon(block_num, &ld->block[0]);

	if (coded) 
	{
		unsigned int * zigzag; 

		if (mp4_state->hdr.ac_pred_flag == 1) {

			if (mp4_state->coeff_pred.predict_dir == TOP)
				zigzag = mp4_tables->alternate_horizontal_scan;
			else
				zigzag = mp4_tables->alternate_vertical_scan;
		}
		else {
			zigzag = mp4_tables->zig_zag_scan;
		}

		i = 1;
		do 
		{
			event = vld_intra_dct();
			
			i+= event.run;
			ld->block[zigzag[i]] = (short) event.level;

			i++;
		} while (! event.last);
	}

	mp4_state->hdr.intrablock_rescaled = ac_rescaling(block_num, &ld->block[0]);
	if (! mp4_state->hdr.intrablock_rescaled)
	{
		ac_recon(block_num, &ld->block[0]);
	}
	ac_store(block_num, &ld->block[0]);

	if (mp4_state->hdr.quant_type == 0)
	{
		iquant(ld->block, 1);
	}
	else 
	{
		iquant_typefirst(ld->block);
	}

	idct(ld->block);

	return 1;
}

/***/

int blockInter(int block_num, int coded)
{
	event_t event;
	unsigned int * zigzag = mp4_tables->zig_zag_scan; // zigzag scan dir
	int i;
	
	clearblock(ld->block); 

	if (mp4_state->hdr.quant_type == 0) 
	{
		int q_scale = mp4_state->hdr.quantizer;
		int q_2scale = q_scale << 1;
		int q_add = (q_scale & 1) ? q_scale : (q_scale - 1);
			
		i = 0;
		do 
		{
			event = vld_inter_dct();

		i+= event.run;
			if (event.level > 0) {
				ld->block[zigzag[i]] = (q_2scale * event.level) + q_add;
			}
			else {
				ld->block[zigzag[i]] = (q_2scale * event.level) - q_add;
			}
			
			
			i++;
		} while (! event.last);
	}
	else 
	{
		int k, m = 0;
		i = 0;

		do 
		{
			event = vld_inter_dct();

			i+= event.run;
	
			k = (event.level > 0) ? 1 : -1;

			assert(ld->block[zigzag[i]] < 2047);
			assert(ld->block[zigzag[i]] > -2048);

			ld->block[zigzag[i]] = ((2 * event.level + k) * mp4_state->hdr.quantizer * 
				mp4_tables->nonintra_quant_matrix[zigzag[i]]) >> 4;

			assert(ld->block[zigzag[i]] < 2047);
			assert(ld->block[zigzag[i]] > -2048);

			m ^= ld->block[zigzag[i]];
			
			
			i++;
		} while (! event.last);

		if (!(m%2)) ld->block[63] ^= 1;
	}

	idct(ld->block);
		
	return 1;
}



static int getDCsizeLum()
{
	int code;


	if (showbits(11) == 1) {
		flushbits(11);
		return 12;
	}
  if (showbits(10) == 1) {
    flushbits(10);
    return 11;
  }
  if (showbits(9) == 1) {
    flushbits(9);
    return 10;
	}
	if (showbits(8) == 1) {
		flushbits(8);
		return 9;
	}
	if (showbits(7) == 1) {
		flushbits(7);
		return 8;
	}
	if (showbits(6) == 1) {
		flushbits(6);
		return 7;
	}  
	if (showbits(5) == 1) {
		flushbits(5);
		return 6;
	}
	if (showbits(4) == 1) {
		flushbits(4);
		return 5;
	}

	code = showbits(3);

	if (code == 1) {
		flushbits(3);
		return 4;
	} else if (code == 2) {
		flushbits(3);
		return 3;
	} else if (code == 3) {
		flushbits(3);
		return 0;
	}

  code = showbits(2);

  if (code == 2) {
		flushbits(2);
		return 2;
	} else if (code == 3) {
		flushbits(2);
		return 1;
	}     

	return 0;
}

static int getDCsizeChr()
{

	if (showbits(12) == 1) {
		flushbits(12);
		return 12;
	}
	if (showbits(11) == 1) {
		flushbits(11);
		return 11;
	}
	if (showbits(10) == 1) {
		flushbits(10);
		return 10;
	}
	if (showbits(9) == 1) {
		flushbits(9);
		return 9;
	}
	if (showbits(8) == 1) {
		flushbits(8);
		return 8;
	}
	if (showbits(7) == 1) {
		flushbits(7);
		return 7;
	}
	if (showbits(6) == 1) {
		flushbits(6);
		return 6;
	}
	if (showbits(5) == 1) {
		flushbits(5);
		return 5;
	}
	if (showbits(4) == 1) {
		flushbits(4);
		return 4;
	} 
	if (showbits(3) == 1) {
		flushbits(3);
		return 3;
	} 

	return (3 - getbits(2));
}



static int getDCdiff(int dct_dc_size)
{
	int code = getbits(dct_dc_size);
	int msb = code >> (dct_dc_size - 1);

	if (msb == 0) {
		return (-1 * (code^((int) pow(2.0,(double) dct_dc_size) - 1)));
	}
  else { 
		return code;
	}
}



static void setDCscaler(int block_num) 
{
	int type = (block_num < 4) ? 0 : 1;
	int quant = mp4_state->hdr.quantizer;

	if (type == 0) {
		if (quant > 0 && quant < 5) 
			mp4_state->hdr.dc_scaler = 8;
		else if (quant > 4 && quant < 9) 
			mp4_state->hdr.dc_scaler = (2 * quant);
		else if (quant > 8 && quant < 25) 
			mp4_state->hdr.dc_scaler = (quant + 8);
		else 
			mp4_state->hdr.dc_scaler = (2 * quant - 16);
	}
  else {
		if (quant > 0 && quant < 5) 
			mp4_state->hdr.dc_scaler = 8;
		else if (quant > 4 && quant < 25) 
			mp4_state->hdr.dc_scaler = ((quant + 13) / 2);
		else 
			mp4_state->hdr.dc_scaler = (quant - 6);
	}
}

/***/

⌨️ 快捷键说明

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