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

📄 getpicture.c

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 C
📖 第 1 页 / 共 2 页
字号:
    	else 
		if(code >= 128) tab = &mpeg3_DCTtab3[(code >> 3) - 16];
    	else 
		if(code >= 64)  tab = &mpeg3_DCTtab4[(code >> 2) - 16];
    	else 
		if(code >= 32)  tab = &mpeg3_DCTtab5[(code >> 1) - 16];
    	else 
		if(code >= 16)  tab = &mpeg3_DCTtab6[code - 16];
    	else 
		{
/*    		fprintf(stderr,"mpeg3video_getmpg2intrablock: invalid Huffman code\n"); */
    		slice->fault = 1;
    		return 1;
    	}

    	mpeg3slice_flushbits(slice_buffer, tab->len);

/* end_of_block */
    	if(tab->run == 64)
    	   	break; 

    	if(tab->run == 65)
		{
/* escape */
    	  	i += mpeg3slice_getbits(slice_buffer, 6);

    	  	val = mpeg3slice_getbits(slice_buffer, 12);
    	  	if((val & 2047) == 0)
			{
// invalid signed_level (escape)
        		slice->fault = 1;
        		return 0;
    	  	}
    	  	if((sign = (val >= 2048)) != 0) val = 4096 - val;
    	}
    	else 
		{
    		i += tab->run;
    		val = tab->level;
    		sign = mpeg3slice_getbit(slice_buffer);
    	}

    	j = (video->altscan ? video->mpeg3_alternate_scan_table : video->mpeg3_zigzag_scan_table)[i];

#ifdef HAVE_MMX
		if(video->have_mmx)
	    	val = (val * slice->quant_scale * qmat[j]);
		else
#endif
    		val = (val * slice->quant_scale * qmat[j]) >> 4;

    	bp[j] = sign ? -val : val;
    	nc++;
	}

	if(j != 0)
	{
/* not a sparse matrix ! */
    	 slice->sparse[comp] = 0;
	}
	return 1;
}


/* decode one non-intra coded MPEG-2 block */

int mpeg3video_getmpg2interblock(mpeg3_slice_t *slice, 
		mpeg3video_t *video, 
		int comp)
{
	int val, i, j, sign, nc;
	unsigned int code;
	mpeg3_DCTtab_t *tab;
	short *bp;
	int *qmat;
	mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;

/* with data partitioning, data always goes to base layer */
  	bp = slice->block[comp];

  	qmat = (comp < 4 || video->chroma_format == CHROMA420)
         ? video->non_intra_quantizer_matrix
         : video->chroma_non_intra_quantizer_matrix;

  	nc = 0;

/* decode AC coefficients */
  	for(i = 0; ; i++)
	{
    	code = mpeg3slice_showbits16(slice_buffer);
    	if(code >= 16384)
		{
    	  if(i == 0) tab = &mpeg3_DCTtabfirst[(code >> 12) - 4];
    	  else      tab = &mpeg3_DCTtabnext[(code >> 12) - 4];
    	}
    	else 
		if(code >= 1024) tab = &mpeg3_DCTtab0[(code >> 8) - 4];
    	else 
		if(code >= 512)  tab = &mpeg3_DCTtab1[(code >> 6) - 8];
    	else 
		if(code >= 256)  tab = &mpeg3_DCTtab2[(code >> 4) - 16];
    	else 
		if(code >= 128)  tab = &mpeg3_DCTtab3[(code >> 3) - 16];
    	else 
		if(code >= 64)   tab = &mpeg3_DCTtab4[(code >> 2) - 16];
    	else 
		if(code >= 32)   tab = &mpeg3_DCTtab5[(code >> 1) - 16];
    	else 
		if(code >= 16)   tab = &mpeg3_DCTtab6[code - 16];
    	else 
		{
// invalid Huffman code
    		slice->fault = 1;
    		return 0;
    	}

    	mpeg3slice_flushbits(slice_buffer, tab->len);

/* end_of_block */
    	if(tab->run == 64)
       		break;          

    	if(tab->run == 65)
		{                 
/* escape */
    		i += mpeg3slice_getbits(slice_buffer, 6);
    		val = mpeg3slice_getbits(slice_buffer, 12);
    		if((val & 2047) == 0)
			{
/*        		fprintf(stderr, "mpeg3video_getmpg2interblock: invalid signed_level (escape)\n"); */
        		slice->fault = 1;
        		return 1;
    		}
    		if((sign = (val >= 2048)) != 0) val = 4096 - val;
    	}
    	else 
		{
    		i += tab->run;
    		val = tab->level;
    		sign = mpeg3slice_getbit(slice_buffer);
    	}

    	j = (video->altscan ? video->mpeg3_alternate_scan_table : video->mpeg3_zigzag_scan_table)[i];

#ifdef HAVE_MMX
 		if(video->have_mmx)
    		val = (((val << 1)+1) * slice->quant_scale * qmat[j]) >> 1;
		else
#endif
     		val = (((val << 1)+1) * slice->quant_scale * qmat[j]) >> 5;

    	bp[j] = sign ? (-val) : val ;
    	nc++;
	}

	if(j != 0) 
	{
      	slice->sparse[comp] = 0;
	}
	return 0;
}


/* decode all macroblocks of the current picture */
int mpeg3video_get_macroblocks(mpeg3video_t *video, int framenum)
{
	unsigned int code;
	mpeg3_slice_buffer_t *slice_buffer; /* Buffer being loaded */
	int i;
	int current_buffer;
	mpeg3_bits_t *vstream = video->vstream;

/* Load every slice into a buffer array */
	video->total_slice_buffers = 0;
	current_buffer = 0;
	while(!mpeg3bits_eof(vstream) && 
		mpeg3bits_showbits32_noptr(vstream) >= MPEG3_SLICE_MIN_START && 
		mpeg3bits_showbits32_noptr(vstream) <= MPEG3_SLICE_MAX_START &&
		video->total_slice_buffers < MPEG3_MAX_CPUS)
	{
/* Initialize the buffer */
		if(current_buffer >= video->slice_buffers_initialized)
			mpeg3_new_slice_buffer(&(video->slice_buffers[video->slice_buffers_initialized++]));
		slice_buffer = &(video->slice_buffers[current_buffer]);
		slice_buffer->buffer_size = 0;
		slice_buffer->current_position = 0;
		slice_buffer->bits_size = 0;
		slice_buffer->done = 0;

/* Read the slice into the buffer including the slice start code */
		do
		{
/* Expand buffer */
			if(slice_buffer->buffer_allocation <= slice_buffer->buffer_size)
				mpeg3_expand_slice_buffer(slice_buffer);

/* Load 1 char into buffer */
			slice_buffer->data[slice_buffer->buffer_size++] = mpeg3bits_getbyte_noptr(vstream);
		}while(!mpeg3bits_eof(vstream) &&
			mpeg3bits_showbits24_noptr(vstream) != MPEG3_PACKET_START_CODE_PREFIX);

/* Pad the buffer to get the last macroblock */
		if(slice_buffer->buffer_allocation <= slice_buffer->buffer_size + 4)
			mpeg3_expand_slice_buffer(slice_buffer);

		slice_buffer->data[slice_buffer->buffer_size++] = 0;
		slice_buffer->data[slice_buffer->buffer_size++] = 0;
		slice_buffer->data[slice_buffer->buffer_size++] = 1;
		slice_buffer->data[slice_buffer->buffer_size++] = 0;
		slice_buffer->bits_size = 0;

#ifndef SDL_THREADS
		pthread_mutex_lock(&(slice_buffer->completion_lock));
#else
		SDL_LockMutex(slice_buffer->completion_lock);
#endif
		fflush(stdout);
		current_buffer++;
		video->total_slice_buffers++;
	}

/* Run the slice decoders */
	if(video->total_slice_buffers > 0)
	{
		for(i = 0; i < video->total_slice_decoders; i++)
		{
			if(i == 0 && video->total_slice_decoders > 1)
			{
				video->slice_decoders[i].current_buffer = 0;
				video->slice_decoders[i].buffer_step = 1;
				video->slice_decoders[i].last_buffer = (video->total_slice_buffers - 1);
			}
			else
			if(i == 1)
			{
				video->slice_decoders[i].current_buffer = video->total_slice_buffers - 1;
				video->slice_decoders[i].buffer_step = -1;
				video->slice_decoders[i].last_buffer = 0;
			}
			else
			{
				video->slice_decoders[i].current_buffer = i;
				video->slice_decoders[i].buffer_step = 1;
				video->slice_decoders[i].last_buffer = video->total_slice_buffers - 1;
			}
#ifndef SDL_THREADS
			pthread_mutex_unlock(&(video->slice_decoders[i].input_lock));
#else
			SDL_UnlockMutex(video->slice_decoders[i].input_lock);
#endif
		}
	}

/* Wait for the slice buffers to finish */
	if(video->total_slice_buffers > 0)
	{
		for(i = 0; i < video->total_slice_buffers; i++)
		{
#ifndef SDL_THREADS
			pthread_mutex_lock(&(video->slice_buffers[i].completion_lock));
			pthread_mutex_unlock(&(video->slice_buffers[i].completion_lock));
#else
			SDL_LockMutex(video->slice_buffers[i].completion_lock);
			SDL_UnlockMutex(video->slice_buffers[i].completion_lock);
#endif
		}

/* Wait for decoders to finish so packages aren't overwritten */
		for(i = 0; i < video->total_slice_decoders; i++)
		{
#ifndef SDL_THREADS
			pthread_mutex_lock(&(video->slice_decoders[i].completion_lock));
#else
			SDL_LockMutex(video->slice_decoders[i].completion_lock);
#endif
		}
	}
	return 0;
}

int mpeg3video_allocate_decoders(mpeg3video_t *video, int decoder_count)
{
	int i;
	int cpus = video->cpus;
	  if (video->total_slice_decoders != cpus)
	{
		for(i = 0; i < video->total_slice_decoders; i++)
		{
			mpeg3_delete_slice_decoder(&(video->slice_decoders[i]));
		}

		for(i = 0; i < cpus && i < MPEG3_MAX_CPUS; i++)
		{
			mpeg3_new_slice_decoder(video, &(video->slice_decoders[i]));
			video->slice_decoders[i].thread_number = i;
		}

		video->total_slice_decoders = cpus;
	}
	return 0;
}

/* decode one frame or field picture */

int mpeg3video_getpicture(mpeg3video_t *video, int framenum)
{
	int i, result = 0;
	int cpus = video->cpus;

	if(video->pict_struct == FRAME_PICTURE && video->secondfield)
	{
/* recover from illegal number of field pictures */
    	video->secondfield = 0;
	}

	if(!video->mpeg2)
	{
		video->current_repeat = video->repeat_count = 0;
	}

	mpeg3video_allocate_decoders(video, cpus);

  	for(i = 0; i < 3; i++)
	{
    	if(video->pict_type == B_TYPE)
		{
			video->newframe[i] = video->auxframe[i];
		}
    	else 
		{
    	  	if(!video->secondfield && !video->current_repeat)
			{
/* Swap refframes for I frames */
        		unsigned char* tmp = video->oldrefframe[i];
        		video->oldrefframe[i] = video->refframe[i];
        		video->refframe[i] = tmp;
    	  	}

    	 	video->newframe[i] = video->refframe[i];
    	}

    	if(video->pict_struct == BOTTOM_FIELD)
		{
/* Only used if fields are in different pictures */
    	    video->newframe[i] += (i == 0) ? video->coded_picture_width : video->chrom_width;
		}
	}


/* The problem is when a B frame lands on the first repeat and is skipped, */
/* the second repeat goes for the same bitmap as the skipped repeat, */
/* so it picks up a frame from 3 frames back. */
/* The first repeat must consititutively read a B frame if its B frame is going to be */
/* used in a later repeat. */
	if(!video->current_repeat)
		if(!(video->skip_bframes && video->pict_type == B_TYPE) || 
			(video->repeat_count >= 100 + 100 * video->skip_bframes))
  			result = mpeg3video_get_macroblocks(video, framenum);

/* Set the frame to display */
	video->output_src = 0;
	if(framenum > -1 && !result)
	{
    	if(video->pict_struct == FRAME_PICTURE || video->secondfield)
		{
     	  	if(video->pict_type == B_TYPE)
			{
				video->output_src = video->auxframe;
			}
     	  	else
			{
				video->output_src = video->oldrefframe;
			}
    	}
    	else 
		{
			mpeg3video_display_second_field(video);
		}
	}

	if(video->mpeg2)
	{
		video->current_repeat += 100;
	}

  	if(video->pict_struct != FRAME_PICTURE) video->secondfield = !video->secondfield;
	return result;
}

⌨️ 快捷键说明

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