📄 mp4_picture.c
字号:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mp4_decoder.h"
#include "mp4_vars.h"
#include "mp4_header.h"
#include "mp4_mblock.h"
#include "transferIDCT.h"
#include "postprocess.h"
#include "yuv2rgb.h"
#include "store.h"
/**
*
**/
void addblock (int comp, int bx, int by, int addflag);
int find_pmv (int block, int comp);
static void make_edge (unsigned char *frame_pic, int width, int height, int edge);
/***/
// 解码和显示一个视频对象平面
void get_mp4picture (unsigned char *bmp, unsigned int stride, int render_flag)
{
mp4_state->hdr.mba = 0;
mp4_state->hdr.mb_xpos = 0;
mp4_state->hdr.mb_ypos = 0;
do {
macroblock();
mp4_state->hdr.mba++;
} while ((nextbits_bytealigned(23) != 0) &&
(mp4_state->hdr.mba < mp4_state->hdr.mba_size));
// 对被解码的帧增加边界
make_edge (frame_ref[0], mp4_state->coded_picture_width, mp4_state->coded_picture_height, 32);
make_edge (frame_ref[1], mp4_state->chrom_width, mp4_state->chrom_height, 16);
make_edge (frame_ref[2], mp4_state->chrom_width, mp4_state->chrom_height, 16);
PictureDisplay(bmp, stride, render_flag);
// 交换帧
{
int i;
unsigned char *tmp;
for (i = 0; i < 3; i++) {
tmp = frame_ref[i];
frame_ref[i] = frame_for[i];
frame_for[i] = tmp;
}
}
}
/***/
void addblock (int comp, int bx, int by, int addflag)
{
int cc, i, iincr;
unsigned char *rfp;
short *bp;
unsigned char *curr[3];
curr[0] = frame_ref[0];
curr[1] = frame_ref[1];
curr[2] = frame_ref[2];
bp = ld->block;
cc = (comp < 4) ? 0 : (comp & 1) + 1;
if (cc == 0)
{
bx <<= 4;
by <<= 4;
rfp = curr[0] + mp4_state->coded_picture_width * (by + ((comp & 2) << 2)) + bx + ((comp & 1) << 3);
iincr = mp4_state->coded_picture_width;
}
else
{
bx <<= 3;
by <<= 3;
rfp = curr[cc] + mp4_state->chrom_width * by + bx;
iincr = mp4_state->chrom_width;
}
if (addflag)
{
for (i = 0; i < 8; i++)
{
rfp[0] = mp4_state->clp[bp[0] + rfp[0]];
rfp[1] = mp4_state->clp[bp[1] + rfp[1]];
rfp[2] = mp4_state->clp[bp[2] + rfp[2]];
rfp[3] = mp4_state->clp[bp[3] + rfp[3]];
rfp[4] = mp4_state->clp[bp[4] + rfp[4]];
rfp[5] = mp4_state->clp[bp[5] + rfp[5]];
rfp[6] = mp4_state->clp[bp[6] + rfp[6]];
rfp[7] = mp4_state->clp[bp[7] + rfp[7]];
bp += 8;
rfp += iincr;
}
} else
{
for (i = 0; i < 8; i++)
{
rfp[0] = mp4_state->clp[bp[0]];
rfp[1] = mp4_state->clp[bp[1]];
rfp[2] = mp4_state->clp[bp[2]];
rfp[3] = mp4_state->clp[bp[3]];
rfp[4] = mp4_state->clp[bp[4]];
rfp[5] = mp4_state->clp[bp[5]];
rfp[6] = mp4_state->clp[bp[6]];
rfp[7] = mp4_state->clp[bp[7]];
bp += 8;
rfp += iincr;
}
}
}
/***/
void addblockIntra (int comp, int bx, int by)
{
int cc, iincr;
unsigned char *rfp;
short *bp;
unsigned char *curr[3];
curr[0] = frame_ref[0];
curr[1] = frame_ref[1];
curr[2] = frame_ref[2];
bp = ld->block;
cc = (comp < 4) ? 0 : (comp & 1) + 1;
if (cc == 0)
{
bx <<= 4;
by <<= 4;
rfp = curr[0] + mp4_state->coded_picture_width * (by + ((comp & 2) << 2)) + bx + ((comp & 1) << 3);
iincr = mp4_state->coded_picture_width;
}
else
{
bx <<= 3;
by <<= 3;
rfp = curr[cc] + mp4_state->chrom_width * by + bx;
iincr = mp4_state->chrom_width;
}
transferIDCT_copy(bp, rfp, iincr);
}
/***/
void addblockInter (int comp, int bx, int by)
{
int cc, iincr;
unsigned char *rfp;
short *bp;
unsigned char *curr[3];
curr[0] = frame_ref[0];
curr[1] = frame_ref[1];
curr[2] = frame_ref[2];
bp = ld->block;
cc = (comp < 4) ? 0 : (comp & 1) + 1;
if (cc == 0)
{
bx <<= 4;
by <<= 4;
rfp = curr[0] + mp4_state->coded_picture_width * (by + ((comp & 2) << 2)) + bx + ((comp & 1) << 3);
iincr = mp4_state->coded_picture_width;
}
else
{
bx <<= 3;
by <<= 3;
rfp = curr[cc] + mp4_state->chrom_width * by + bx;
iincr = mp4_state->chrom_width;
}
transferIDCT_add(bp, rfp, iincr);
}
int find_pmv (int block, int comp)
{
int p1, p2, p3;
int xin1, xin2, xin3;
int yin1, yin2, yin3;
int vec1, vec2, vec3;
int x = mp4_state->hdr.mb_xpos;
int y = mp4_state->hdr.mb_ypos;
if ((y == 0) && ((block == 0) || (block == 1)))
{
if ((x == 0) && (block == 0))
return 0;
else if (block == 1)
return mp4_state->MV[comp][0][y+1][x+1];
else // block == 0
return mp4_state->MV[comp][1][y+1][x+1-1];
}
else
{
x++;
y++;
switch (block)
{
case 0:
vec1 = 1; yin1 = y; xin1 = x-1;
vec2 = 2; yin2 = y-1; xin2 = x;
vec3 = 2; yin3 = y-1; xin3 = x+1;
break;
case 1:
vec1 = 0; yin1 = y; xin1 = x;
vec2 = 3; yin2 = y-1; xin2 = x;
vec3 = 2; yin3 = y-1; xin3 = x+1;
break;
case 2:
vec1 = 3; yin1 = y; xin1 = x-1;
vec2 = 0; yin2 = y; xin2 = x;
vec3 = 1; yin3 = y; xin3 = x;
break;
default:
vec1 = 2; yin1 = y; xin1 = x;
vec2 = 0; yin2 = y; xin2 = x;
vec3 = 1; yin3 = y; xin3 = x;
break;
}
p1 = mp4_state->MV[comp][vec1][yin1][xin1];
p2 = mp4_state->MV[comp][vec2][yin2][xin2];
p3 = mp4_state->MV[comp][vec3][yin3][xin3];
return mmin(mmax(p1, p2), mmin(mmax(p2, p3), mmax(p1, p3)));
}
}
/***/
// 对被解码的帧增加边界
void make_edge (unsigned char *frame_pic,
int edged_width, int edged_height, int edge)
{
int j;
int width = edged_width - (2*edge);
int height = edged_height - (2*edge);
unsigned char *p_border;
unsigned char *p_border_top, *p_border_bottom;
unsigned char *p_border_top_ref, *p_border_bottom_ref;
// 左右边界
p_border = frame_pic;
for (j = 0; j < height; j++)
{
unsigned char border_left = *(p_border);
unsigned char border_right = *(p_border + (width-1));
memset((p_border - edge), border_left, edge);
memset((p_border + width), border_right, edge);
p_border += edged_width;
}
// 上下边界
p_border_top_ref = frame_pic;
p_border_bottom_ref = frame_pic + (edged_width * (height -1));
p_border_top = p_border_top_ref - (edge * edged_width);
p_border_bottom = p_border_bottom_ref + edged_width;
for (j = 0; j < edge; j++)
{
memcpy(p_border_top, p_border_top_ref, width);
memcpy(p_border_bottom, p_border_bottom_ref, width);
p_border_top += edged_width;
p_border_bottom += edged_width;
}
// 角
{
unsigned char * p_left_corner_top = frame_pic - edge - (edge * edged_width);
unsigned char * p_right_corner_top = p_left_corner_top + edge + width;
unsigned char * p_left_corner_bottom = frame_pic + (edged_width * height) - edge;
unsigned char * p_right_corner_bottom = p_left_corner_bottom + edge + width;
char left_corner_top = *(frame_pic);
char right_corner_top = *(frame_pic + (width-1));
char left_corner_bottom = *(frame_pic + (edged_width * (height-1)));
char right_corner_bottom = *(frame_pic + (edged_width * (height-1)) + (width-1));
for (j = 0; j < edge; j++)
{
memset(p_left_corner_top, left_corner_top, edge);
memset(p_right_corner_top, right_corner_top, edge);
memset(p_left_corner_bottom, left_corner_bottom, edge);
memset(p_right_corner_bottom, right_corner_bottom, edge);
p_left_corner_top += edged_width;
p_right_corner_top += edged_width;
p_left_corner_bottom += edged_width;
p_right_corner_bottom += edged_width;
}
}
}
/***/
// 在显示或写入一个文件前对一个帧缓存重新排序
void PictureDisplay(unsigned char *bmp, unsigned int stride, int render_flag)
{
#ifdef _DECORE
if (render_flag)
{
if (mp4_state->post_flag)
{
postprocess(frame_ref, mp4_state->coded_picture_width,
display_frame, mp4_state->horizontal_size,
mp4_state->horizontal_size, mp4_state->vertical_size,
&mp4_state->quant_store[1][1], (DEC_MBC+1), mp4_state->pp_options);
mp4_state->convert_yuv(display_frame[0], mp4_state->hdr.width,
display_frame[1], display_frame[2], (mp4_state->hdr.width>>1),
bmp, mp4_state->hdr.width, mp4_state->flag_invert * mp4_state->hdr.height,
stride);
}
else
{
mp4_state->convert_yuv(frame_ref[0], mp4_state->coded_picture_width,
frame_ref[1], frame_ref[2], (mp4_state->coded_picture_width>>1),
bmp, mp4_state->hdr.width, mp4_state->flag_invert * mp4_state->hdr.height,
stride);
}
}
#else
// 输出到一个文件
storeframe (frame_ref, mp4_state->coded_picture_width, mp4_state->vertical_size);
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -