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

📄 slice.c

📁 jpeg and mpeg 编解码技术源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "../mpeg3private.h"
#include "mpeg3video.h"
#include "mpeg3videoprotos.h"
#include "slice.h"

#ifndef SDL_THREADS
#include <pthread.h>
#else
#include "SDL.h"
#include "SDL_thread.h"
#endif
#include <stdlib.h>

#define CLIP(x)  ((x) >= 0 ? ((x) < 255 ? (x) : 255) : 0)

#ifndef _MSC_VER
static unsigned long long MMX_128 = 0x80008000800080LL;
#else
static u_int64_t MMX_128 = 0x80008000800080;
#endif

int mpeg3_new_slice_buffer(mpeg3_slice_buffer_t *slice_buffer)
{
#ifndef SDL_THREADS
	pthread_mutexattr_t mutex_attr;
#endif

	slice_buffer->data = malloc(1024);
	slice_buffer->buffer_size = 0;
	slice_buffer->buffer_allocation = 1024;
	slice_buffer->current_position = 0;
	slice_buffer->bits_size = 0;
	slice_buffer->bits = 0;
	slice_buffer->done = 0;
#ifndef SDL_THREADS
	pthread_mutexattr_init(&mutex_attr);
//	pthread_mutexattr_setkind_np(&mutex_attr, PTHREAD_MUTEX_FAST_NP);
	pthread_mutex_init(&(slice_buffer->completion_lock), &mutex_attr);
#else
	slice_buffer->completion_lock = SDL_CreateMutex();
#endif
	return 0;
}

int mpeg3_delete_slice_buffer(mpeg3_slice_buffer_t *slice_buffer)
{
	free(slice_buffer->data);
#ifndef SDL_THREADS
	pthread_mutex_destroy(&(slice_buffer->completion_lock));
#else
	SDL_DestroyMutex(slice_buffer->completion_lock);
#endif
	return 0;
}

int mpeg3_expand_slice_buffer(mpeg3_slice_buffer_t *slice_buffer)
{
	int i;
	unsigned char *new_buffer = malloc(slice_buffer->buffer_allocation * 2);
	for(i = 0; i < slice_buffer->buffer_size; i++)
		new_buffer[i] = slice_buffer->data[i];
	free(slice_buffer->data);
	slice_buffer->data = new_buffer;
	slice_buffer->buffer_allocation *= 2;
	return 0;
}

/* limit coefficients to -2048..2047 */

/* move/add 8x8-Block from block[comp] to refframe */

static __inline int mpeg3video_addblock(mpeg3_slice_t *slice, 
		mpeg3video_t *video, 
		int comp, 
		int bx, 
		int by, 
		int dct_type, 
		int addflag)
{
	int cc, i, iincr;
	unsigned char *rfp;
	short *bp;
	int spar = slice->sparse[comp];
/* color component index */
  	cc = (comp < 4) ? 0 : (comp & 1) + 1; 

  	if(cc == 0)
	{   
/* luminance */
    	if(video->pict_struct == FRAME_PICTURE)
		{
      		if(dct_type)
			{
/* field DCT coding */
        		rfp = video->newframe[0] + 
              		video->coded_picture_width * (by + ((comp & 2) >> 1)) + bx + ((comp & 1) << 3);
        		iincr = (video->coded_picture_width << 1);
      		}
      		else
			{
/* frame DCT coding */
        		rfp = video->newframe[0] + 
             		video->coded_picture_width * (by + ((comp & 2) << 2)) + bx + ((comp & 1) << 3);
        		iincr = video->coded_picture_width;
      		}
		}
    	else 
		{
/* field picture */
      		rfp = video->newframe[0] + 
           		(video->coded_picture_width << 1) * (by + ((comp & 2) << 2)) + bx + ((comp & 1) << 3);
      		iincr = (video->coded_picture_width << 1);
    	}
 	}
  	else 
	{
/* chrominance */

/* scale coordinates */
    	if(video->chroma_format != CHROMA444) bx >>= 1;
    	if(video->chroma_format == CHROMA420) by >>= 1;
    	if(video->pict_struct == FRAME_PICTURE)
		{
    		if(dct_type && (video->chroma_format != CHROMA420))
			{
/* field DCT coding */
        		rfp = video->newframe[cc]
            		  + video->chrom_width * (by + ((comp & 2) >> 1)) + bx + (comp & 8);
        		iincr = (video->chrom_width << 1);
    		}
    		else 
			{
/* frame DCT coding */
        		rfp = video->newframe[cc]
            		  + video->chrom_width * (by + ((comp & 2) << 2)) + bx + (comp & 8);
        		iincr = video->chrom_width;
    		}
    	}
    	else 
		{
/* field picture */
    		rfp = video->newframe[cc]
            	  + (video->chrom_width << 1) * (by + ((comp & 2) << 2)) + bx + (comp & 8);
    		iincr = (video->chrom_width << 1);
    	}
  	}

  	bp = slice->block[comp];

	if(addflag)
	{
#ifdef HAVE_MMX
		if(video->have_mmx)
		{
    		if(spar)
			{
    	   __asm__ __volatile__(
            	"movq       (%2),  %%mm6\n"  /* 4 blockvals */
            	"pxor       %%mm4, %%mm4\n"
            	"punpcklwd  %%mm6, %%mm6\n"
            	"punpcklwd  %%mm6, %%mm6\n"
            	".align 8\n"
            	"1:"
                	"movq       (%1),  %%mm0\n"     /* 8 rindex1 */
                	"movq       %%mm0, %%mm2\n"
                	"punpcklbw  %%mm4, %%mm0\n"
                	"punpckhbw  %%mm4, %%mm2\n"
                	"paddw      %%mm6, %%mm0\n"
                	"paddw      %%mm6, %%mm2\n"

                	"packuswb   %%mm2, %%mm0\n"
                	"movq       %%mm0, (%1)\n"

                	"leal       (%1, %3), %1\n"
            	  "loop       1b\n"
            	  :              /* scr   dest */
            	  : "c" (8),"r" (rfp), "r" (bp), "r" (iincr)
                	);
    		}
    		else 
			{
    	   __asm__ __volatile__(
        		 "pxor    %%mm4, %%mm4\n"

        		 ".align 8\n"
        		 "1:"
        		   "movq       (%2), %%mm0\n"   /* 8 rfp 0 1 2 3 4 5 6 7*/
        		   "movq       (%1), %%mm6\n"   /* 4 blockvals 0 1 2 3 */

        		   "movq       %%mm0, %%mm2\n"
        		   "movq       8(%1), %%mm5\n"  /* 4 blockvals 0 1 2 3 */
        		   "punpcklbw  %%mm4, %%mm0\n"  /* 0 2 4 6 */
        		   "punpckhbw  %%mm4, %%mm2\n"  /* 1 3 5 7 */

        		   "paddw      %%mm6, %%mm0\n"
        		   "paddw      %%mm5, %%mm2\n"
        		   "packuswb   %%mm2, %%mm0\n"

        		   "addl       $16, %1\n"
        		   "movq       %%mm0, (%2)\n"

        		   "leal       (%2,%3), %2\n"
        		 "loop       1b\n"
        		 :              /* scr   dest */
        		 : "c" (8),"r" (bp), "r" (rfp), "r" (iincr)
    		);
    		}
		}
		else
#endif
			for(i = 0; i < 8; i++)
			{
    			rfp[0] = CLIP(bp[0] + rfp[0]);
    			rfp[1] = CLIP(bp[1] + rfp[1]);
    			rfp[2] = CLIP(bp[2] + rfp[2]);
    			rfp[3] = CLIP(bp[3] + rfp[3]);
    			rfp[4] = CLIP(bp[4] + rfp[4]);
    			rfp[5] = CLIP(bp[5] + rfp[5]);
    			rfp[6] = CLIP(bp[6] + rfp[6]);
    			rfp[7] = CLIP(bp[7] + rfp[7]);
    			rfp += iincr;
    			bp += 8;
			}
  	}
  	else 
  	{
/* libtool PIC causes problems here */
#if defined(HAVE_MMX) && !defined(MPEG4IP)
		if(video->have_mmx)
		{
    		if(spar) 
			{
            __asm__ __volatile__(
            	"movd       (%2),           %%mm0\n"    /* " 0 0 0  v1" */
            	"punpcklwd  %%mm0,          %%mm0\n"    /* " 0 0 v1 v1" */
            	"punpcklwd  %%mm0,          %%mm0\n"
            	"paddw      MMX_128,        %%mm0\n"
            	"packuswb   %%mm0,          %%mm0\n"
            	"leal       (%0,%1,2),      %%eax\n"

            	"movq        %%mm0,         (%0, %1)\n"
            	"movq        %%mm0,         (%%eax)\n"
            	"leal        (%%eax,%1,2),  %0\n"
            	"movq        %%mm0,         (%%eax, %1)\n"

            	"movq        %%mm0,         (%0)\n"
            	"leal        (%0,%1,2),     %%eax\n"
            	"movq        %%mm0,         (%0, %1)\n"

            	"movq        %%mm0,         (%%eax)\n"
            	"movq        %%mm0,         (%%eax, %1)\n"
            	:
            	: "D" (rfp), "c" (iincr), "b" (bp)
            	: "eax");
    		}
    		else 
			{
    		__asm__ __volatile__(
            	"movq        MMX_128,%%mm4\n"
            	".align 8\n"
            	"1:"
            	  "movq      (%1),   %%mm0\n"
            	  "movq      8(%1),  %%mm1\n"
            	  "paddw     %%mm4,  %%mm0\n"

            	  "movq      16(%1), %%mm2\n"
            	  "paddw     %%mm4,  %%mm1\n"

            	  "movq      24(%1), %%mm3\n"
            	  "paddw     %%mm4,  %%mm2\n"

            	  "packuswb  %%mm1,  %%mm0\n"
            	  "paddw     %%mm4,  %%mm3\n"

            	  "addl $32, %1\n"
            	  "packuswb  %%mm3,  %%mm2\n"

            	  "movq   %%mm0, (%2)\n"

            	  "movq   %%mm2, (%2,%3)\n"

            	  "leal       (%2,%3,2), %2\n"
            	"loop       1b\n"
            	:
            	: "c" (4), "r" (bp), "r" (rfp), "r" (iincr)
        	);
    		}
		}
		else
#endif /* HAVE_MMX */
    		for(i = 0; i < 8; i++)
			{
    			rfp[0] = CLIP(bp[0] + 128);
    			rfp[1] = CLIP(bp[1] + 128);
    			rfp[2] = CLIP(bp[2] + 128);
    			rfp[3] = CLIP(bp[3] + 128);
    			rfp[4] = CLIP(bp[4] + 128);
    			rfp[5] = CLIP(bp[5] + 128);
    			rfp[6] = CLIP(bp[6] + 128);
    			rfp[7] = CLIP(bp[7] + 128);
    			rfp+= iincr;
    			bp += 8;
    		}
  	}
	return 0;
}

int mpeg3_decode_slice(mpeg3_slice_t *slice)
{
	mpeg3video_t *video = slice->video;
	int comp;
	int mb_type, cbp, motion_type = 0, dct_type;
	int macroblock_address, mba_inc, mba_max;
	int slice_vert_pos_ext;
	unsigned int code;
	int bx, by;
	int dc_dct_pred[3];
	int mv_count, mv_format, mvscale;
	int pmv[2][2][2], mv_field_sel[2][2];
	int dmv, dmvector[2];
	int qs;
	int stwtype, stwclass; 
	int snr_cbp;
	int i;
	mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;

/* number of macroblocks per picture */
  	mba_max = video->mb_width * video->mb_height;

/* field picture has half as many macroblocks as frame */
	if(video->pict_struct != FRAME_PICTURE)
	    mba_max >>= 1; 

/* macroblock address */
  	macroblock_address = 0; 
/* first macroblock in slice is not skipped */
  	mba_inc = 0;
  	slice->fault = 0;

	code = mpeg3slice_getbits(slice_buffer, 32);
/* decode slice header (may change quant_scale) */
    slice_vert_pos_ext = mpeg3video_getslicehdr(slice, video);

/* reset all DC coefficient and motion vector predictors */
    dc_dct_pred[0] = dc_dct_pred[1] = dc_dct_pred[2] = 0;
    pmv[0][0][0] = pmv[0][0][1] = pmv[1][0][0] = pmv[1][0][1] = 0;
    pmv[0][1][0] = pmv[0][1][1] = pmv[1][1][0] = pmv[1][1][1] = 0;

  	for(i = 0; 
		slice_buffer->current_position < slice_buffer->buffer_size; 
		i++)
	{
		if(mba_inc == 0)
		{
/* Done */
			if(!mpeg3slice_showbits(slice_buffer, 23)) return 0;
/* decode macroblock address increment */
    		mba_inc = mpeg3video_get_macroblock_address(slice);

        	if(slice->fault) return 1;

    		if(i == 0)
			{
/* Get the macroblock_address */
				macroblock_address = ((slice_vert_pos_ext << 7) + (code & 255) - 1) * video->mb_width + mba_inc - 1;
/* first macroblock in slice: not skipped */
				mba_inc = 1;
			}
		}

        if(slice->fault) return 1;

    	if(macroblock_address >= mba_max)
		{
/* mba_inc points beyond picture dimensions */
      		/*fprintf(stderr, "mpeg3_decode_slice: too many macroblocks in picture\n"); */
      		return 1;
    	}

/* not skipped */
    	if(mba_inc == 1)
		{
			mpeg3video_macroblock_modes(slice, 
				video, 
				&mb_type, 
				&stwtype, 
				&stwclass,
        		&motion_type, 
				&mv_count, 
				&mv_format, 

⌨️ 快捷键说明

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