/* mpeg2dec.c, main(), initialization, option processing */ /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group 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 MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, 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. * */ #include #include #include #include #include #include #include #include #include #include #define GLOBAL #include "config.h" #include "global.h" #include "common.h" /* private prototypes */ static int video_sequence _ANSI_ARGS_((int *framenum)); static int Decode_Bitstream _ANSI_ARGS_((void)); static int Headers _ANSI_ARGS_((void)); static void Initialize_Sequence _ANSI_ARGS_((void)); static void Initialize_Decoder _ANSI_ARGS_((void)); static void Deinitialize_Sequence _ANSI_ARGS_((void)); static void Process_Options _ANSI_ARGS_((int argc, char *argv[])); int ysk, usk, vsk, psk; #if OLD static int Get_Val _ANSI_ARGS_((char *argv[])); #endif /* #define DEBUG */ static void Clear_Options(); #ifdef DEBUG static void Print_Options(); #endif struct sockaddr_un ys = { AF_UNIX, "new0.Y" }; struct sockaddr_un us = { AF_UNIX, "new0.U" }; struct sockaddr_un vs = { AF_UNIX, "new0.V" }; struct sockaddr_un ps = { AF_UNIX, "new0.P" }; int main(argc, argv) int argc; char *argv[]; { int ret, code; int i, ysk2, usk2, vsk2, psk2; struct sockaddr_in sin; struct hostent *phostent; /******************THIS PART WAS CREATED BY KENT MEDIANET**********************/ FILE *net_par; char srv_id[10], srv_ip[50], srv_port[10]; dynamic_bypass_on = 1; frame_bypass_on = 0; dec_f_num = 0; Clear_Options(); /* decode command line arguments */ Process_Options(argc, argv); /******************THIS PART WAS CREATED BY KENT MEDIANET**********************/ if ((net_par = fopen("net.par", "r")) == NULL) printf("Usage:[net.par] could not opened\n"); else { fscanf(net_par, "%s\t%s\t%s\n", &srv_id, &srv_ip, &srv_port); } fclose(net_par); printf("XCODER: detected server's IP %s and server's port %s\n", srv_ip, srv_port); sscanf(argv[7], "%d", &flag); ysk2 = socket(AF_UNIX, SOCK_STREAM, 0); if (bind(ysk2, &ys, sizeof(ys)) == -1) { perror("socket y bind.\n"); close(ysk2); unlink(ys.sun_path); exit(1); } listen(ysk2, 1); ysk = accept(ysk2, &ys, &i); usk2 = socket(AF_UNIX, SOCK_STREAM, 0); if (bind(usk2, &us, sizeof(us)) == -1) { perror("socket y bind.\n"); close(usk2); unlink(us.sun_path); exit(1); } listen(usk2, 1); usk = accept(usk2, &us, &i); vsk2 = socket(AF_UNIX, SOCK_STREAM, 0); if (bind(vsk2, &vs, sizeof(vs)) == -1) { perror("socket y bind.\n"); close(vsk2); unlink(vs.sun_path); exit(1); } listen(vsk2, 1); vsk = accept(vsk2, &vs, &i); psk2 = socket(AF_UNIX, SOCK_STREAM, 0); if (bind(psk2, &ps, sizeof(vs)) == -1) { perror("socket p bind.\n"); close(psk2); unlink(ps.sun_path); exit(1); } listen(psk2, 1); psk = accept(psk2, &ps, &i); /* printf("server ip %s\n",srv_ip); printf("server port %d\n",atoi(srv_port));*/ #ifdef DEBUG Print_Options(); #endif ld = &base; /* select base layer context */ /* open MPEG base layer bitstream file(s) */ /* NOTE: this is either a base layer stream or a spatial enhancement stream */ if ((base.Infile = open(Main_Bitstream_Filename, O_RDONLY | O_BINARY)) < 0) { fprintf(stderr, "Base layer input file %s not found\n", Main_Bitstream_Filename); exit(1); } flagseek = 0; /* printf("XCODER: trying connect to the server %s\n",srv_ip); */ base.Infile = socket(AF_INET, SOCK_STREAM, 0); bzero(&sin, sizeof(sin)); sin.sin_family = AF_INET; phostent = gethostbyname(srv_ip); memcpy(&(sin.sin_addr), phostent->h_addr, phostent->h_length); sin.sin_port = htons(atoi(srv_port)); if (connect(base.Infile, (struct sockaddr *) &sin, sizeof(sin)) == -1) { printf("Error !!!\n"); exit(1); } /* printf("XCODER: server connected.\n"); */ if (base.Infile != 0) { Initialize_Buffer(); if (Show_Bits(8) == 0x47) { sprintf(Error_Text, "Decoder currently does not parse transport streams\n"); Error(Error_Text); } next_start_code(); code = Show_Bits(32); switch (code) { case SEQUENCE_HEADER_CODE: break; case PACK_START_CODE: System_Stream_Flag = 1; case VIDEO_ELEMENTARY_STREAM: System_Stream_Flag = 1; break; default: sprintf(Error_Text, "Unable to recognize stream type\n"); Error(Error_Text); break; } /* lseek(base.Infile, 0l, 0); */ flagseek = 1; Initialize_Buffer(); } if (base.Infile != 0) { /* lseek(base.Infile, 0l, 0); */ flagseek = 1; } Initialize_Buffer(); if (Two_Streams) { ld = &enhan; /* select enhancement layer context */ if ( (enhan.Infile = open(Enhancement_Layer_Bitstream_Filename, O_RDONLY | O_BINARY)) < 0) { sprintf(Error_Text, "enhancment layer bitstream file %s not found\n", Enhancement_Layer_Bitstream_Filename); Error(Error_Text); } Initialize_Buffer(); ld = &base; } Initialize_Decoder(); ret = Decode_Bitstream(); close(base.Infile); if (Two_Streams) close(enhan.Infile); close(ysk); close(usk); close(vsk); close(psk); close(ysk2); close(usk2); close(vsk2); close(psk2); return 0; } /* IMPLEMENTAION specific rouintes */ static void Initialize_Decoder() { int i; /* Clip table */ if (!(Clip = (unsigned char *) malloc(1024))) Error("Clip[] malloc failed\n"); Clip += 384; for (i = -384; i < 640; i++) Clip[i] = (i < 0) ? 0 : ((i > 255) ? 255 : i); /* IDCT */ if (Reference_IDCT_Flag) Initialize_Reference_IDCT(); else Initialize_Fast_IDCT(); } /* mostly IMPLEMENTAION specific rouintes */ static void Initialize_Sequence() { int cc, size; static int Table_6_20[3] = { 6, 8, 12 }; /* check scalability mode of enhancement layer */ if (Two_Streams && (enhan.scalable_mode != SC_SNR) && (base.scalable_mode != SC_DP)) Error("unsupported scalability mode\n"); /* force MPEG-1 parameters for proper decoder behavior */ /* see ISO/IEC 13818-2 section D.9.14 */ if (!base.MPEG2_Flag) { progressive_sequence = 1; progressive_frame = 1; picture_structure = FRAME_PICTURE; frame_pred_frame_dct = 1; chroma_format = CHROMA420; matrix_coefficients = 5; } /* round to nearest multiple of coded macroblocks */ /* ISO/IEC 13818-2 section 6.3.3 sequence_header() */ mb_width = (horizontal_size + 15) / 16; mb_height = (base.MPEG2_Flag && !progressive_sequence) ? 2 * ((vertical_size + 31) / 32) : (vertical_size + 15) / 16; Coded_Picture_Width = 16 * mb_width; Coded_Picture_Height = 16 * mb_height; /* ISO/IEC 13818-2 sections 6.1.1.8, 6.1.1.9, and 6.1.1.10 */ Chroma_Width = (chroma_format == CHROMA444) ? Coded_Picture_Width : Coded_Picture_Width >> 1; Chroma_Height = (chroma_format != CHROMA420) ? Coded_Picture_Height : Coded_Picture_Height >> 1; /* derived based on Table 6-20 in ISO/IEC 13818-2 section 6.3.17 */ block_count = Table_6_20[chroma_format - 1]; for (cc = 0; cc < 3; cc++) { if (cc == 0) size = Coded_Picture_Width * Coded_Picture_Height; else size = Chroma_Width * Chroma_Height; if (! (backward_reference_frame[cc] = (unsigned char *) malloc(size))) Error("backward_reference_frame[] malloc failed\n"); if (! (forward_reference_frame[cc] = (unsigned char *) malloc(size))) Error("forward_reference_frame[] malloc failed\n"); if (!(auxframe[cc] = (unsigned char *) malloc(size))) Error("auxframe[] malloc failed\n"); if (Ersatz_Flag) if (!(substitute_frame[cc] = (unsigned char *) malloc(size))) Error("substitute_frame[] malloc failed\n"); if (base.scalable_mode == SC_SPAT) { /* this assumes lower layer is 4:2:0 */ if (!(llframe0[cc] = (unsigned char *) malloc( (lower_layer_prediction_horizontal_size * lower_layer_prediction_vertical_size) / (cc ? 4 : 1)))) Error("llframe0 malloc failed\n"); if (!(llframe1[cc] = (unsigned char *) malloc( (lower_layer_prediction_horizontal_size * lower_layer_prediction_vertical_size) / (cc ? 4 : 1)))) Error("llframe1 malloc failed\n"); } } /* SCALABILITY: Spatial */ if (base.scalable_mode == SC_SPAT) { if (! (lltmp = (short *) malloc(lower_layer_prediction_horizontal_size * ((lower_layer_prediction_vertical_size * vertical_subsampling_factor_n) / vertical_subsampling_factor_m) * sizeof(short)))) Error("lltmp malloc failed\n"); } #ifdef DISPLAY if (Output_Type == T_X11) { Initialize_Display_Process(""); Initialize_Dither_Matrix(); } #endif /* DISPLAY */ } void Error(text) char *text; { fprintf(stderr, text); exit(1); } /* Trace_Flag output */ void Print_Bits(code, bits, len) int code, bits, len; { int i; for (i = 0; i < len; i++) printf("%d", (code >> (bits - 1 - i)) & 1); } /* option processing */ static void Process_Options(argc, argv) int argc; /* argument count */ char *argv[]; /* argument vector */ { int i, LastArg, NextArg; /* at least one argument should be present */ if (argc < 2) { printf("\n%s, %s\n", Version, Author); printf("Usage: mpeg2decode {options}\n\ Options: -b file main bitstream (base or spatial enhancement layer)\n\ -cn file conformance report (n: level)\n\ -e file enhancement layer bitstream (SNR or Data Partitioning)\n\ -f store/display interlaced video in frame format\n\ -g concatenated file format for substitution method (-x)\n\ -in file information & statistics report (n: level)\n\ -l file file name pattern for lower layer sequence\n\ (for spatial scalability)\n\ -on file output format (0:YUV 1:SIF 2:TGA 3:PPM 4:X11 5:X11HiQ)\n\ -q disable warnings to stderr\n\ -r use double precision reference IDCT\n\ -t enable low level tracing to stdout\n\ -u file print user_data to stdio or file\n\ -vn verbose output (n: level)\n\ -x file filename pattern of picture substitution sequence\n\n\ File patterns: for sequential filenames, \"printf\" style, e.g. rec%%d\n\ or rec%%d%%c for fieldwise storage\n\ Levels: 0:none 1:sequence 2:picture 3:slice 4:macroblock 5:block\n\n\ Example: mpeg2decode -b bitstream.mpg -f -r -o0 rec%%d\n\ \n"); exit(0); } Output_Type = -1; i = 1; /* command-line options are proceeded by '-' */ while (i < argc) { /* check if this is the last argument */ LastArg = ((argc - i) == 1); /* parse ahead to see if another flag immediately follows current argument (this is used to tell if a filename is missing) */ if (!LastArg) NextArg = (argv[i + 1][0] == '-'); else NextArg = 0; /* second character, [1], after '-' is the switch */ if (argv[i][0] == '-') { switch (toupper(argv[i][1])) { /* third character. [2], is the value */ case 'B': Main_Bitstream_Flag = 1; if (NextArg || LastArg) { printf ("ERROR: -b must be followed the main bitstream filename\n"); } else Main_Bitstream_Filename = argv[++i]; break; case 'C': #ifdef VERIFY Verify_Flag = atoi(&argv[i][2]); if ((Verify_Flag < NO_LAYER) || (Verify_Flag > ALL_LAYERS)) { printf("ERROR: -c level (%d) out of range [%d,%d]\n", Verify_Flag, NO_LAYER, ALL_LAYERS); exit(ERROR); } #else /* VERIFY */ printf ("This program not compiled for Verify_Flag option\n"); #endif /* VERIFY */ break; case 'E': Two_Streams = 1; /* either Data Partitioning (DP) or SNR Scalability enhancment */ if (NextArg || LastArg) { printf("ERROR: -e must be followed by filename\n"); exit(ERROR); } else Enhancement_Layer_Bitstream_Filename = argv[++i]; break; case 'F': Frame_Store_Flag = 1; break; case 'G': Big_Picture_Flag = 1; break; case 'I': #ifdef VERIFY Stats_Flag = atoi(&argv[i][2]); #else /* VERIFY */ printf ("WARNING: This program not compiled for -i option\n"); #endif /* VERIFY */ break; case 'L': /* spatial scalability flag */ Spatial_Flag = 1; if (NextArg || LastArg) { printf("ERROR: -l must be followed by filename\n"); exit(ERROR); } else Lower_Layer_Picture_Filename = argv[++i]; break; case 'O': Output_Type = atoi(&argv[i][2]); if ((Output_Type == 4) || (Output_Type == 5)) Output_Picture_Filename = ""; /* no need of filename */ else if (NextArg || LastArg) { printf("ERROR: -o must be followed by filename\n"); exit(ERROR); } else /* filename is separated by space, so it becomes the next argument */ Output_Picture_Filename = argv[++i]; #ifdef DISPLAY if (Output_Type == T_X11HIQ) { hiQdither = 1; Output_Type = T_X11; } #endif /* DISPLAY */ break; case 'Q': Quiet_Flag = 1; break; case 'R': Reference_IDCT_Flag = 1; break; case 'T': #ifdef TRACE Trace_Flag = 1; #else /* TRACE */ printf ("WARNING: This program not compiled for -t option\n"); #endif /* TRACE */ break; case 'U': User_Data_Flag = 1; case 'V': #ifdef VERBOSE Verbose_Flag = atoi(&argv[i][2]); #else /* VERBOSE */ printf("This program not compiled for -v option\n"); #endif /* VERBOSE */ break; case 'X': Ersatz_Flag = 1; if (NextArg || LastArg) { printf("ERROR: -x must be followed by filename\n"); exit(ERROR); } else Substitute_Picture_Filename = argv[++i]; break; default: fprintf(stderr, "undefined option -%c ignored. Exiting program\n", argv[i][1]); exit(ERROR); } /* switch() */ } /* if argv[i][0] == '-' */ i++; /* check for bitstream filename argument (there must always be one, at the very end of the command line arguments */ } /* while() */ /* options sense checking */ if (Main_Bitstream_Flag != 1) { printf("There must be a main bitstream specified (-b filename)\n"); } /* force display process to show frame pictures */ if ((Output_Type == 4 || Output_Type == 5) && Frame_Store_Flag) Display_Progressive_Flag = 1; else Display_Progressive_Flag = 0; #ifdef VERIFY /* parse the bitstream, do not actually decode it completely */ #if 0 if (Output_Type == -1) { Decode_Layer = Verify_Flag; printf("FYI: Decoding bitstream elements up to: %s\n", Layer_Table[Decode_Layer]); } else #endif Decode_Layer = ALL_LAYERS; #endif /* VERIFY */ /* no output type specified */ if (Output_Type == -1) { Output_Type = 9; Output_Picture_Filename = ""; } #ifdef DISPLAY if (Output_Type == T_X11) { if (Frame_Store_Flag) Display_Progressive_Flag = 1; else Display_Progressive_Flag = 0; Frame_Store_Flag = 1; /* to avoid calling dither() twice */ } #endif } #ifdef OLD /* this is an old routine used to convert command line arguments into integers */ static int Get_Val(argv) char *argv[]; { int val; if (sscanf(argv[1] + 2, "%d", &val) != 1) return 0; while (isdigit(argv[1][2])) argv[1]++; return val; } #endif static int Headers() { int ret; ld = &base; /* return when end of sequence (0) or picture header has been parsed (1) */ ret = Get_Hdr(); if (Two_Streams) { ld = &enhan; if (Get_Hdr() != ret && !Quiet_Flag) fprintf(stderr, "streams out of sync\n"); ld = &base; } return ret; } static int Decode_Bitstream() { int ret; int Bitstream_Framenum; Bitstream_Framenum = 0; for (;;) { #ifdef VERIFY Clear_Verify_Headers(); #endif /* VERIFY */ ret = Headers(); if (ret == 1) { ret = video_sequence(&Bitstream_Framenum); } else return (ret); } } static void Deinitialize_Sequence() { int i; /* clear flags */ base.MPEG2_Flag = 0; for (i = 0; i < 3; i++) { free(backward_reference_frame[i]); free(forward_reference_frame[i]); free(auxframe[i]); if (base.scalable_mode == SC_SPAT) { free(llframe0[i]); free(llframe1[i]); } } if (base.scalable_mode == SC_SPAT) free(lltmp); #ifdef DISPLAY if (Output_Type == T_X11) Terminate_Display_Process(); #endif } static int video_sequence(Bitstream_Framenumber) int *Bitstream_Framenumber; { int Bitstream_Framenum; int Sequence_Framenum; int Return_Value; Bitstream_Framenum = *Bitstream_Framenumber; Sequence_Framenum = 0; Initialize_Sequence(); /* decode picture whose header has already been parsed in Decode_Bitstream() */ Decode_Picture(Bitstream_Framenum, Sequence_Framenum); /* update picture numbers */ if (!Second_Field) { Bitstream_Framenum++; Sequence_Framenum++; } /* loop through the rest of the pictures in the sequence */ while ((Return_Value = Headers())) { strcpy(line, "frame\n"); write(psk, line, 256); Decode_Picture(Bitstream_Framenum, Sequence_Framenum); if (!Second_Field) { Bitstream_Framenum++; Sequence_Framenum++; } } /* put last frame */ if (Sequence_Framenum != 0) { sprintf(line, "%s", "last frame \n"); write(psk, line, 256); Output_Last_Frame_of_Sequence(Bitstream_Framenum); } Deinitialize_Sequence(); #ifdef VERIFY Clear_Verify_Headers(); #endif /* VERIFY */ *Bitstream_Framenumber = Bitstream_Framenum; return (Return_Value); } static void Clear_Options() { Verbose_Flag = 0; Output_Type = 0; Output_Picture_Filename = " "; hiQdither = 0; Output_Type = 0; Frame_Store_Flag = 0; Spatial_Flag = 0; Lower_Layer_Picture_Filename = " "; Reference_IDCT_Flag = 0; Trace_Flag = 0; Quiet_Flag = 0; Ersatz_Flag = 0; Substitute_Picture_Filename = " "; Two_Streams = 0; Enhancement_Layer_Bitstream_Filename = " "; Big_Picture_Flag = 0; Main_Bitstream_Flag = 0; Main_Bitstream_Filename = " "; Verify_Flag = 0; Stats_Flag = 0; User_Data_Flag = 0; } /******************THIS PART WAS CREATED BY KENT MEDIANET**********************/ void Read_Bypasspar_For_Decoder() { FILE *bp; if ((bp = fopen("bypass.par", "r")) == NULL) printf("FILE could not be opened\n"); else fscanf(bp, "%d %d", &Bd, &Bf); fclose(bp); if (ECHO) { printf("decoder read the bypass.par current F= DB=%d,DF%d\n",Bd, Bf ); fflush(bp); } } void Creat_Frame_Bypasspar_For_Encoder(int d_bypass, int f_bypass, int f_num) { FILE *gbp; chdir("./test"); memset(gopinfo, '\0', 100); sprintf(gopinfo, "encframebypass%d.txt", f_num); if ((gbp = fopen(gopinfo, "w")) == NULL) printf("encframebypass%d.txt could not opened\n",f_num); else { fprintf(gbp, "%d %d %d\n", d_bypass, f_bypass, f_num); } fclose(gbp); if (ECHO)printf("decoder finished creating encframebypass file \n"); } #ifdef DEBUG static void Print_Options() { printf("Verbose_Flag = %d\n", Verbose_Flag); printf("Output_Type = %d\n", Output_Type); printf("Output_Picture_Filename = %s\n", Output_Picture_Filename); printf("hiQdither = %d\n", hiQdither); printf("Output_Type = %d\n", Output_Type); printf("Frame_Store_Flag = %d\n", Frame_Store_Flag); printf("Spatial_Flag = %d\n", Spatial_Flag); printf("Lower_Layer_Picture_Filename = %s\n", Lower_Layer_Picture_Filename); printf("Reference_IDCT_Flag = %d\n", Reference_IDCT_Flag); printf("Trace_Flag = %d\n", Trace_Flag); printf("Quiet_Flag = %d\n", Quiet_Flag); printf("Ersatz_Flag = %d\n", Ersatz_Flag); printf("Substitute_Picture_Filename = %s\n", Substitute_Picture_Filename); printf("Two_Streams = %d\n", Two_Streams); printf("Enhancement_Layer_Bitstream_Filename = %s\n", Enhancement_Layer_Bitstream_Filename); printf("Big_Picture_Flag = %d\n", Big_Picture_Flag); printf("Main_Bitstream_Flag = %d\n", Main_Bitstream_Flag); printf("Main_Bitstream_Filename = %s\n", Main_Bitstream_Filename); printf("Verify_Flag = %d\n", Verify_Flag); printf("Stats_Flag = %d\n", Stats_Flag); printf("User_Data_Flag = %d\n", User_Data_Flag); } #endif