📄 image.c
字号:
/*!
* \file
* Image.c
* \brief
* Decode a Slice
*
* \author
* Main contributors (see contributors.h for copyright, address and affiliation details)
*
* Inge Lille-Lang鴜 <inge.lille-langoy@telenor.com>
* Rickard Sjoberg <rickard.sjoberg@era.ericsson.se>
* Jani Lainema <jani.lainema@nokia.com>
* Sebastian Purreiter <sebastian.purreiter@mch.siemens.de>
* Byeong-Moon Jeon <jeonbm@lge.com>
* Thomas Wedi <wedi@tnt.uni-hannover.de>
* Gabi Blaettermann <blaetter@hhi.de>
*/
#include "contributors.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/timeb.h>
#include <string.h>
#include "global.h"
#include "elements.h"
#include "image.h"
#ifdef _ADAPT_LAST_GROUP_
int *last_P_no;
#endif
/************************************************************************
*
* Name : decode_one_frame()
*
* Description: decodes one I- or P-frame
*
************************************************************************/
int decode_one_frame(struct img_par *img,struct inp_par *inp, struct snr_par *snr)
{
int current_header;
Slice *currSlice = img->currentSlice;
time_t ltime1; /* for time measurement */
time_t ltime2;
#ifdef WIN32
struct _timeb tstruct1;
struct _timeb tstruct2;
#else
// struct tm *l_time;
struct timeb tstruct1;
struct timeb tstruct2;
// time_t now;
#endif
int tmp_time; /* time used by decoding the last frame */
#ifdef WIN32
_ftime (&tstruct1); /* start time ms */
#else
ftime (&tstruct1); /* start time ms */
#endif
time( <ime1 ); /* start time s */
currSlice->next_header = 0;
while (currSlice->next_header != EOS && currSlice->next_header != SOP)
{
/* set the corresponding read functions */
start_slice(img, inp);
/* read new slice */
current_header = read_new_slice(img, inp);
if (inp->symbol_mode == CABAC)
{
init_contexts_MotionInfo(img, currSlice->mot_ctx, 1);
init_contexts_TextureInfo(img,currSlice->tex_ctx, 1);
}
if (current_header == EOS)
return EOS;
/* init new frame */
if (current_header == SOP)
init_frame(img, inp);
// printf("read new slice %d %d %d %d %d %d %d\n",img->currentSlice->start_mb_nr,img->currentSlice->qp,
// img->currentSlice->format, img->currentSlice->picture_id, current_header, img->format,
// img->current_slice_nr);
/* decode main slice information */
if (current_header == SOP || current_header == SOS)
decode_one_slice(img,inp);
img->current_slice_nr++;
}
loopfilter(img);
if(img->number == 0)
copy2mref(img);
/* else StW
copy2mref_1(img);
*/
if (p_ref)
find_snr(snr,img,p_ref,inp->postfilter); /* if ref sequence exist */
#ifdef WIN32
_ftime (&tstruct2); /* end time ms */
#else
ftime (&tstruct2); /* end time ms */
#endif
time( <ime2 ); /* end time sec */
tmp_time=(ltime2*1000+tstruct2.millitm) - (ltime1*1000+tstruct1.millitm);
tot_time=tot_time + tmp_time;
if(img->type == INTRA_IMG) // I picture
fprintf(stdout,"%3d(I) %3d %5d %7.4f %7.4f %7.4f %5d\n",
frame_no, img->tr, img->qp,snr->snr_y,snr->snr_u,snr->snr_v,tmp_time);
else if(img->type == INTER_IMG_1 || img->type == INTER_IMG_MULT) // P pictures
fprintf(stdout,"%3d(P) %3d %5d %7.4f %7.4f %7.4f %5d\n",
frame_no, img->tr, img->qp,snr->snr_y,snr->snr_u,snr->snr_v,tmp_time);
else // B pictures
fprintf(stdout,"%3d(B) %3d %5d %7.4f %7.4f %7.4f %5d\n",
frame_no, img->tr, img->qp,snr->snr_y,snr->snr_u,snr->snr_v,tmp_time);
fflush(stdout);
// getchar();
if(img->type == INTER_IMG_1 || img->type == INTER_IMG_MULT) // P pictres
copy_Pframe(img, inp->postfilter); // imgY-->imgY_prev, imgUV-->imgUV_prev
else // I or B pictures
write_frame(img,inp->postfilter,p_out); /* write image to output YUV file */
if(img->type <= INTRA_IMG) // I or P pictures
img->number++;
else
Bframe_ctr++; // B pictures
exit_frame(img, inp);
img->current_mb_nr = 0;
return (SOP);
}
/************************************************************************
*
* Name : copy2mref()
*
* Description: store reconstructed frames in multiple
* reference buffer
*
************************************************************************/
void copy2mref(struct img_par *img)
{
int i,j,uv;
img->frame_cycle=img->number % img->buf_cycle;
for (j=0; j < img->height; j++)
for (i=0; i < img->width; i++)
mref[img->frame_cycle][j][i]=imgY[j][i];
for (uv=0; uv < 2; uv++)
for (i=0; i < img->width_cr; i++)
for (j=0; j < img->height_cr; j++)
mcef[img->frame_cycle][uv][j][i]=imgUV[uv][j][i];/* just copy 1/1 pix, interpolate "online" */
}
/*!
* \fn find_snr()
* \brief Find PSNR for all three components.Compare decoded frame with
* the original sequence. Read inp->jumpd frames to reflect frame skipping.
*/
void find_snr(
struct snr_par *snr, /*!< pointer to snr parameters */
struct img_par *img, /*!< pointer to image parameters */
FILE *p_ref, /*!< filestream to reference YUV file */
int postfilter) /*!< postfilterin on (=1) or off (=1) */
{
int i,j;
int diff_y,diff_u,diff_v;
int uv;
int status;
#ifndef _ADAPT_LAST_GROUP_
byte diff;
#else
static int p_frame_no;
#endif
#ifndef _ADAPT_LAST_GROUP_
if(img->type<=INTRA_IMG) // I, P pictures
frame_no=img->number*P_interval;
else // B pictures
{
diff=nextP_tr-img->tr;
frame_no=(img->number-1)*P_interval-diff;
}
#else
if (img->type <= INTRA_IMG) // I, P
{
if (img->number > 0)
frame_no = p_frame_no += (256 + img->tr - last_P_no[0]) % 256;
else
frame_no = p_frame_no = 0;
}
else // B
{
frame_no = p_frame_no - (256 + nextP_tr - img->tr) % 256;
}
#endif
rewind(p_ref);
status = fseek (p_ref, frame_no*img->height*img->width*3/2, 0);
if (status != 0) {
printf(" Error in seeking img->tr: %d\n", img->tr);
exit (-1);
}
for (j=0; j < img->height; j++)
for (i=0; i < img->width; i++)
imgY_ref[j][i]=fgetc(p_ref);
for (uv=0; uv < 2; uv++)
for (j=0; j < img->height_cr ; j++)
for (i=0; i < img->width_cr; i++)
imgUV_ref[uv][j][i]=fgetc(p_ref);
img->quad[0]=0;
diff_y=0;
for (i=0; i < img->width; ++i)
{
for (j=0; j < img->height; ++j)
{
diff_y += img->quad[abs(imgY[j][i]-imgY_ref[j][i])];
}
}
/* Chroma */
diff_u=0;
diff_v=0;
for (i=0; i < img->width_cr; ++i)
{
for (j=0; j < img->height_cr; ++j)
{
diff_u += img->quad[abs(imgUV_ref[0][j][i]-imgUV[0][j][i])];
diff_v += img->quad[abs(imgUV_ref[1][j][i]-imgUV[1][j][i])];
}
}
/* Collecting SNR statistics */
if (diff_y != 0)
{
snr->snr_y=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)diff_y)); /* luma snr for current frame */
}
if (diff_u != 0)
{
snr->snr_u=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)(4*diff_u))); /* chroma snr for current frame */
snr->snr_v=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)(4*diff_v))); /* chroma snr for current frame */
}
if (img->number == 0) /* first */
{
snr->snr_y1=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)diff_y)); /* keep luma snr for first frame */
snr->snr_u1=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)(4*diff_u))); /* keep chroma snr for first frame */
snr->snr_v1=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)(4*diff_v))); /* keep chroma snr for first frame */
snr->snr_ya=snr->snr_y1;
snr->snr_ua=snr->snr_u1;
snr->snr_va=snr->snr_v1;
}
else
{
snr->snr_ya=(float)(snr->snr_ya*(img->number+Bframe_ctr)+snr->snr_y)/(img->number+Bframe_ctr+1); /* average snr chroma for all frames */
snr->snr_ua=(float)(snr->snr_ua*(img->number+Bframe_ctr)+snr->snr_u)/(img->number+Bframe_ctr+1); /* average snr luma for all frames */
snr->snr_va=(float)(snr->snr_va*(img->number+Bframe_ctr)+snr->snr_v)/(img->number+Bframe_ctr+1); /* average snr luma for all frames */
}
}
/*!
* \fn loopfilter()
* \brief Filter to reduce blocking artifacts. The filter strengh
* is QP dependent.
*/
static unsigned char
overallActivity[256], qp_overallActivity = 255;
static int
beta;
void loopfilter(struct img_par *img)
{
static int MAP[32];
// byte imgY_tmp[288][352]; /* temp luma image */
// byte imgUV_tmp[2][144][176]; /* temp chroma image */
int x,y,y4,x4,k,uv,str1,str2;
if (qp_overallActivity != img->qp)
{
int
i, alpha,
ALPHA_TABLE[32] = {
0, 0, 0, 0, 0, 0, 0, 0,
3, 3, 3, 7, 7, 7, 12, 17,
17, 22, 28, 34, 40, 47, 60, 67,
82, 89,112,137,153,187,213,249
},
BETA_TABLE[32] = {
0, 0, 0, 0, 0, 0, 0, 0,
3, 3, 3, 4, 4, 4, 6, 6,
6, 7, 8, 8, 9, 9, 10, 10,
11, 11, 12, 12, 13, 13, 14, 14
};
for (i=0; i<32; i++)
MAP[i] = QP2QUANT[i]-1;
/*
* ALPHA(img->qp) = ceil(2.0 * MAP(img->qp) * ln(MAP(img->qp)))
*/
alpha = ALPHA_TABLE[img->qp];
/*
* BETA(img->qp) = floor(4.0 * log(MAP[img->qp]) + 0.5)
*/
beta = BETA_TABLE[img->qp];
for (k=0; k<256; k++)
if (2*k >= alpha+(alpha/2))
overallActivity[k] = 1;
else if (2*k >= alpha)
overallActivity[k] = 2;
else
overallActivity[k] = 3;
qp_overallActivity = img->qp;
}
/* Luma hor */
for(y=0;y<img->height;y++)
for(x=0;x<img->width;x++)
imgY_tmp[y][x]=imgY[y][x];
for(y=0;y<img->height;y++)
{
y4=y/4;
for(x=4;x<img->width;x=x+4)
{
x4=x/4;
str1 = loopb[x4][y4+1];
str2 = loopb[x4+1][y4+1];
if((str1!=0)&&(str2!=0))
{
/*
* Copy one line of 4+4 reconstruction pels into the filtering buffer.
*/
for(k=0;k<8;k++)
img->li[k]=imgY_tmp[y][x-4+k];
/*
* Check for longer filtering on macroblock border if either block is intracoded.
*/
if(!(x4%4) && (str1 == 3 || str2 == 3))
{
if(loop(img,str1,str2, 1, 0))
{
imgY_tmp[y][x-4+6] = img->lu[6];
imgY[y][x-3] = img->lu[1];
imgY[y][x+2] = img->lu[6];
}
}
else
loop(img,str1,str2, 0, 0);
/*
* Place back the filtered values into the filtered reconstruction buffer.
*/
for (k=2;k<6;k++)
imgY[y][x-4+k]=img->lu[k];
}
}
}
/* Luma vert */
for(y=0;y<img->height;y++)
for(x=0;x<img->width;x++)
imgY_tmp[y][x]=imgY[y][x];
for(x=0;x<img->width;x++)
{
x4=x/4;
for(y=4;y<img->height;y=y+4)
{
y4=y/4;
str1 = loopb[x4+1][y4];
str2 = loopb[x4+1][y4+1];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -