mp4_picture.c
来自「实现在linux下的mpeg4编解码」· C语言 代码 · 共 435 行
C
435 行
/************************************************************************** * * * This code has been developed by Andrea Graziani. This software is an * * implementation of a part of one or more MPEG-4 Video tools as * * specified in ISO/IEC 14496-2 standard. Those intending to use this * * software module in hardware or software products are advised that its * * use may infringe existing patents or copyrights, and any such use * * would be at such party's own risk. The original developer of this * * software module and his/her company, and subsequent editors and their * * companies (including Project Mayo), will have no liability for use of * * this software or modifications or derivatives thereof. * * * * Project Mayo gives users of the Codec a license to this software * * module or modifications thereof for use in hardware or software * * products claiming conformance to the MPEG-4 Video Standard as * * described in the Open DivX license. * * * * The complete Open DivX license can be found at * * http://www.projectmayo.com/opendivx/license.php * * * **************************************************************************//*** Copyright (C) 2001 - Project Mayo * * Andrea Graziani (Ag) * * DivX Advanced Research Center <darc@projectmayo.com>***/// 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);/***/// Purpose: decode and display a Vopvoid 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)); // add edge to decoded frame 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); // exchange ref and for frames { 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; } }}/***/// Purpose: move/add 8x8 block to curr_framevoid 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; /* color component index */ if (cc == 0) // luminance { // pixel coordinates bx <<= 4; by <<= 4; // frame DCT coding rfp = curr[0] + mp4_state->coded_picture_width * (by + ((comp & 2) << 2)) + bx + ((comp & 1) << 3); iincr = mp4_state->coded_picture_width; } else // chrominance { // pixel coordinates bx <<= 3; by <<= 3; // frame DCT coding 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; /* color component index */ if (cc == 0) // luminance { // pixel coordinates bx <<= 4; by <<= 4; // frame DCT coding rfp = curr[0] + mp4_state->coded_picture_width * (by + ((comp & 2) << 2)) + bx + ((comp & 1) << 3); iincr = mp4_state->coded_picture_width; } else // chrominance { // pixel coordinates bx <<= 3; by <<= 3; // frame DCT coding rfp = curr[cc] + mp4_state->chrom_width * by + bx; iincr = mp4_state->chrom_width; }/*** for (int i = 0; i < 8; i++) { rfp[0] = clp[bp[0]]; rfp[1] = clp[bp[1]]; rfp[2] = clp[bp[2]]; rfp[3] = clp[bp[3]]; rfp[4] = clp[bp[4]]; rfp[5] = clp[bp[5]]; rfp[6] = clp[bp[6]]; rfp[7] = clp[bp[7]]; bp += 8; rfp += iincr; }***/ 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; /* color component index */ if (cc == 0) // luminance { // pixel coordinates bx <<= 4; by <<= 4; // frame DCT coding rfp = curr[0] + mp4_state->coded_picture_width * (by + ((comp & 2) << 2)) + bx + ((comp & 1) << 3); iincr = mp4_state->coded_picture_width; } else // chrominance { // pixel coordinates bx <<= 3; by <<= 3; // frame DCT coding rfp = curr[cc] + mp4_state->chrom_width * by + bx; iincr = mp4_state->chrom_width; }/*** for (int i = 0; i < 8; i++) { rfp[0] = clp[bp[0] + rfp[0]]; rfp[1] = clp[bp[1] + rfp[1]]; rfp[2] = clp[bp[2] + rfp[2]]; rfp[3] = clp[bp[3] + rfp[3]]; rfp[4] = clp[bp[4] + rfp[4]]; rfp[5] = clp[bp[5] + rfp[5]]; rfp[6] = clp[bp[6] + rfp[6]]; rfp[7] = clp[bp[7] + rfp[7]]; bp += 8; rfp += iincr; }***/ transferIDCT_add(bp, rfp, iincr);}/***/// int x, y: block coord// int block block num// int mv comp (0: x, 1: y)//// Purpose: compute motion vector predictionint 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 { // considerate border (avoid increment inside each single array index) 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: // case 3 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 p1 + p2 + p3 - mmax (p1, mmax (p2, p3)) - mmin (p1, mmin (p2, p3)); 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; // left and right edges 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; } // top and bottom edges 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; } // corners { 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; } }}/***/// Purpose: manages a one frame buffer for re-ordering frames prior to // displaying or writing to a filevoid 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 // output on a file storeframe (frame_ref, mp4_state->coded_picture_width, mp4_state->vertical_size);#endif}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?