📄 getpic.c
字号:
/************************************************************************ * * getpic.c, picture decoding for tmndecode (H.263 decoder) * Copyright (C) 1995, 1996 Telenor R&D, Norway * * Contacts: * Robert Danielsen <Robert.Danielsen@nta.no> * * Telenor Research and Development http://www.nta.no/brukere/DVC/ * P.O.Box 83 tel.: +47 63 84 84 00 * N-2007 Kjeller, Norway fax.: +47 63 81 00 76 * * Copyright (C) 1997 University of BC, Canada * Modified by: Mike Gallant <mikeg@ee.ubc.ca> * Guy Cote <guyc@ee.ubc.ca> * Berna Erol <bernae@ee.ubc.ca> * * Contacts: * Micheal Gallant <mikeg@ee.ubc.ca> * * UBC Image Processing Laboratory http://www.ee.ubc.ca/image * 2356 Main Mall tel.: +1 604 822 4051 * Vancouver BC Canada V6T1Z4 fax.: +1 604 822 5949 * ************************************************************************//* Disclaimer of Warranty * * These software programs are available to the user without any license fee * or royalty on an "as is" basis. The University of British Columbia * disclaims any and all warranties, whether express, implied, or * statuary, including any implied warranties or merchantability or of * fitness for a particular purpose. In no event shall the * copyright-holder be liable for any incidental, punitive, or * consequential damages of any kind whatsoever arising from the use of * these programs. * * This disclaimer of warranty extends to the user of these programs and * user's customers, employees, agents, transferees, successors, and * assigns. * * The University of British Columbia does not represent or warrant that the * programs furnished hereunder are free of infringement of any * third-party patents. * * Commercial implementations of H.263, including shareware, are subject to * royalty fees to patent holders. Many of these patents are general * enough such that they are unavoidable regardless of implementation * design. * *//* modified to support annex O true B frames, mikeg@ee.ubc.ca * * modified by Wayne Ellis BT Labs to run Annex E Arithmetic Decoding * <ellis_w_wayne@bt-web.bt.co.uk> * * based on mpeg2decode, (C) 1994, MPEG Software Simulation Group and * mpeg2play, (C) 1994 Stefan Eckart <stefan@lis.e-technik.tu-muenchen.de> */#include <stdio.h>#include <stdlib.h>#include <string.h>#include "config.h"#include "tmndec.h"#include "global.h"#include "indices.h"#include "sactbls.h"static int coded_map[MBR + 1][MBC + 1];static int quant_map[MBR + 1][MBC + 1];static int STRENGTH[] = {1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12};static int STRENGTH1[] = {1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4};static int STRENGTH2[] = {1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3};/* private prototypes */static void get_I_P_MBs _ANSI_ARGS_ ((int framenum, int gob));static void get_B_MBs _ANSI_ARGS_ ((int framenum));static void get_EI_EP_MBs _ANSI_ARGS_ ((int framenum));static void clearblock _ANSI_ARGS_ ((int comp));static int motion_decode _ANSI_ARGS_ ((int vec, int pmv));static int find_pmv _ANSI_ARGS_ ((int x, int y, int block, int comp));static void addblock _ANSI_ARGS_ ((int comp, int bx, int by, int addflag));static void reconblock_b _ANSI_ARGS_ ((int comp, int bx, int by, int mode, int bdx, int bdy));static void find_bidir_limits _ANSI_ARGS_ ((int vec, int *start, int *stop, int nhv));static void find_bidir_chroma_limits _ANSI_ARGS_ ((int vec, int *start, int *stop));static void make_edge_image _ANSI_ARGS_ ((unsigned char *src, unsigned char *dst, int width, int height, int edge));static void init_enhancement_layer _ANSI_ARGS_((int layer));void edge_filter _ANSI_ARGS_ ((unsigned char *lum, unsigned char *Cb, unsigned char *Cr, int width, int height));void horiz_edge_filter _ANSI_ARGS_ ((unsigned char *rec, int width, int height, int chr));void vert_edge_filter _ANSI_ARGS_ ((unsigned char *rec, int width, int height, int chr));void vert_post_filter (unsigned char *rec, int width, int height, int chr);void horiz_post_filter (unsigned char *rec, int width, int height, int chr);void PostFilter (unsigned char *lum, unsigned char *Cb, unsigned char *Cr, int width, int height);/* reference picture selection */int get_reference_picture(void);void store_picture(int);/* error concealment */void conceal_missing_gobs(int start_mb_row_missing, int number_of_mb_rows_missing);/********************************************************************** * * Name: getpicture * Description: decode and display one picture * Input: frame number * Returns: * Side effects: * * Date: 971102 Author: mikeg@ee.ubc.ca * * ***********************************************************************/void getpicture (int *framenum, int gob){ unsigned char *tmp; int i, store_pb, quality=0; static int absolute_temp_ref = 0; static int prev_temp_ref = 0; switch (pict_type) { case PCT_INTRA: case PCT_INTER: case PCT_PB: case PCT_IPB: enhance_pict = NO; if (0 == UFEP && plus_type) { mv_outside_frame = prev_mv_outside_frame; deblocking_filter_mode = prev_df; adv_pred_mode = prev_adv_pred; overlapping_MC = prev_obmc; use_4mv = prev_4mv; long_vectors = prev_long_vectors; syntax_arith_coding = prev_sac; advanced_intra_coding = prev_aic; slice_structured_mode = prev_slice_struct; reference_picture_selection_mode = prev_rps; independently_segmented_decoding_mode = prev_isd; alternative_inter_VLC_mode = prev_aivlc; modified_quantization_mode = prev_mq; } for (i = 0; i < 3; i++) { tmp = prev_frame[i]; prev_I_P_frame[i] = prev_frame[i] = next_I_P_frame[i]; next_I_P_frame[i] = current_frame[i] = tmp; } /* if the picture header is missing, assume temp_ref increments */ /* not done yet*/ /* Annex N: get the correct reference picture for prediction */ if (reference_picture_selection_mode) { if (-1 == (quality = get_reference_picture())) break; if (quality > 256) { fprintf(stderr,"completely out of sync -- waiting for I-frame\n"); stop_decoder = 1; break; } }#ifdef DEBUG if (temp_ref < prev_temp_ref) prev_temp_ref -= 256; absolute_temp_ref += temp_ref - prev_temp_ref; prev_temp_ref = temp_ref; fprintf(stdout, "%d\n", absolute_temp_ref);#endif if ((mv_outside_frame) && (*framenum > 0)) { make_edge_image (prev_I_P_frame[0], edgeframe[0], coded_picture_width, coded_picture_height, 32); make_edge_image (prev_I_P_frame[1], edgeframe[1], chrom_width, chrom_height, 16); make_edge_image (prev_I_P_frame[2], edgeframe[2], chrom_width, chrom_height, 16); } get_I_P_MBs (*framenum, gob); store_pb = pb_frame; pb_frame = 0; if (deblocking_filter_mode) edge_filter (current_frame[0], current_frame[1], current_frame[2], coded_picture_width, coded_picture_height); pb_frame = store_pb; if (pb_frame) { if (deblocking_filter_mode) edge_filter(bframe[0],bframe[1],bframe[2], coded_picture_width,coded_picture_height); } PictureDisplay(framenum); if (reference_picture_selection_mode) store_picture((pict_type == PCT_INTRA) ? 0 : quality); if (1 == UFEP) { prev_mv_outside_frame = mv_outside_frame; prev_sac = syntax_arith_coding; prev_adv_pred = adv_pred_mode; prev_aic = advanced_intra_coding; prev_df = deblocking_filter_mode; prev_slice_struct = slice_structured_mode; prev_rps = reference_picture_selection_mode; prev_isd = independently_segmented_decoding_mode; prev_aivlc = alternative_inter_VLC_mode; prev_mq = modified_quantization_mode; prev_long_vectors = long_vectors; prev_obmc = overlapping_MC; prev_4mv = use_4mv; } break; case PCT_B: if (enhancement_layer_num > 1) enhance_pict = YES; else enhance_pict = NO; for (i = 0; i < 3; i++) { current_frame[i] = bframe[i]; } /* Forward prediction */ make_edge_image (prev_I_P_frame[0], edgeframe[0], coded_picture_width, coded_picture_height, 32); make_edge_image (prev_I_P_frame[1], edgeframe[1], chrom_width, chrom_height, 16); make_edge_image (prev_I_P_frame[2], edgeframe[2], chrom_width, chrom_height, 16); /* Backward prediction */ make_edge_image (next_I_P_frame[0], nextedgeframe[0], coded_picture_width, coded_picture_height, 32); make_edge_image (next_I_P_frame[1], nextedgeframe[1], chrom_width, chrom_height, 16); make_edge_image (next_I_P_frame[2], nextedgeframe[2], chrom_width, chrom_height, 16); get_B_MBs (*framenum); PictureDisplay(framenum); break; case PCT_EI: case PCT_EP: enhance_pict = YES; if (!enhancement_layer_init[enhancement_layer_num-2]) { init_enhancement_layer(enhancement_layer_num-2); enhancement_layer_init[enhancement_layer_num-2] = ON; } for (i = 0; i < 3; i++) { tmp = prev_enhancement_frame[enhancement_layer_num-2][i]; prev_enhancement_frame[enhancement_layer_num-2][i] = current_enhancement_frame[enhancement_layer_num-2][i]; current_enhancement_frame[enhancement_layer_num-2][i] = tmp; } if (scalability_mode >= 3) { UpsampleReferenceLayerPicture(); curr_reference_frame[0] = upsampled_reference_frame[0]; curr_reference_frame[1] = upsampled_reference_frame[1]; curr_reference_frame[2] = upsampled_reference_frame[2]; } else { curr_reference_frame[0] = current_frame[0]; curr_reference_frame[1] = current_frame[1]; curr_reference_frame[2] = current_frame[2]; } make_edge_image (prev_enhancement_frame[enhancement_layer_num-2][0], enhance_edgeframe[enhancement_layer_num-2][0], coded_picture_width, coded_picture_height, 32); make_edge_image (prev_enhancement_frame[enhancement_layer_num-2][1], enhance_edgeframe[enhancement_layer_num-2][1], chrom_width, chrom_height, 16); make_edge_image (prev_enhancement_frame[enhancement_layer_num-2][2], enhance_edgeframe[enhancement_layer_num-2][2], chrom_width, chrom_height, 16); get_EI_EP_MBs (*framenum); if (deblocking_filter_mode) edge_filter (current_enhancement_frame[enhancement_layer_num-2][0], current_enhancement_frame[enhancement_layer_num-2][1], current_enhancement_frame[enhancement_layer_num-2][2], coded_picture_width, coded_picture_height); store_one (enhance_recon_file_name[enhancement_layer_num-2], current_enhancement_frame[enhancement_layer_num-2], 0, coded_picture_width, vertical_size); break; default: break; }}/* decode all macroblocks of the current picture */static int change_of_quant_tab_10[32] = {0, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3};static int change_of_quant_tab_11[32] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, -5};static void get_I_P_MBs (int framenum, int gob){ int comp; int MBA, MBAmax; int bx, by; int COD = 0, MCBPC, CBPY, CBP = 0, CBPB = 0, MODB = 0, Mode = 0, DQUANT; int COD_index, CBPY_index, MODB_index, DQUANT_index, MCBPC_index; int INTRADC_index, YCBPB_index, UVCBPB_index, mvdbx_index, mvdby_index; int mvx = 0, mvy = 0, mvy_index, mvx_index, pmv0, pmv1, xpos, ypos, i, k; int mvdbx = 0, mvdby = 0, pmvdbx, pmvdby, YCBPB, UVCBPB, gobheader_read; int startmv, stopmv, offset, bsize, last_done = 0, pCBP = 0, pCBPB = 0, pCOD = 0, pMODB = 0; int DQ_tab[4] = {-1, -2, 1, 2}; short *bp; int long_vectors_bak; int tmp = 0; int pnewgob = 0; /* Error concealment variables */ int pypos = 0; int start_mb_row_missing, number_of_mb_rows_missing; /* variables used in advanced intra coding mode */ int INTRA_AC_DC = 0, INTRA_AC_DC_index; short *store_qcoeff; int quality=0; int decode_last_mb = 0; int dont_reconstruct_next_mb; /* number of macroblocks per picture */ MBAmax = mb_width * mb_height; gob -= 1; /* 1 was added in getheader() */ MBA = 0; /* macroblock address */ newgob = 0; xpos = ypos = 0; /* mark MV's above the picture */ for (i = 1; i < mb_width + 1; i++) { for (k = 0; k < 5; k++) { MV[0][k][0][i] = NO_VEC; MV[1][k][0][i] = NO_VEC; } modemap[0][i] = MODE_INTRA; } /* zero MV's on the sides of the picture */ for (i = 0; i < mb_height + 1; i++) { for (k = 0; k < 5; k++) { MV[0][k][i][0] = 0; MV[1][k][i][0] = 0; MV[0][k][i][mb_width + 1] = 0; MV[1][k][i][mb_width + 1] = 0; } modemap[i][0] = MODE_INTRA; modemap[i][mb_width + 1] = MODE_INTRA; } /* initialize the qcoeff used in advanced intra coding */ if (advanced_intra_coding) { /* store the qcoeff for the frame */ if ((store_qcoeff = (short *) calloc (64 * MBAmax * blk_cnt, sizeof (short))) == 0) { fprintf (stderr, "getMB(): Couldn't allocate store_qcoeff.\n"); exit (-1); } } fault = 0; gobheader_read = 0; /* if a gob with GN != 0 was present as the first gob * of a picture, decode the rest of the gob header */ if (gob) goto getgobhrd; for (;;) { if (MBA >= MBAmax) { /* all macroblocks decoded */ memcpy(anchorframemodemap,modemap,(sizeof(int)*(MBR+1)*(MBC+2)) ); return; } if (trace) fprintf (trace_file, "frame %d, MB %d\n", framenum, MBA);resync: /* This version of the decoder does not resync on every possible * error, and it does not do all possible error checks. It is not * difficult to make it much more error robust, but I do not think it * is necessary to include this in the freely available version. */ if (fault) { printf ("Warning: A Fault Condition Has Occurred - Resyncing \n"); startcode (); /* sync on new startcode */ fault = 0; } if (!(showbits (22) >> 6)) { /* startcode */ startcode (); /* in case of byte aligned start code, ie. PSTUF, GSTUF or ESTUF is * used */ if (showbits (22) == (32 | SE_CODE)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -