home *** CD-ROM | disk | FTP | other *** search
-
- /* --- C ---
- ************************************************************************
- *
- * Filename : decode.c
- * Description : Decoding of MPEG-Frames
- * Part of : SECMPEG
- *
- * Version : 1.0
- * Language : C
- * For machine : SunOS 4.1.x, INTERACTIVE Unix 2.2.1, Linux, MS-DOS
- * Compile as : see Makefile
- *
- * Authors : Juergen Meyer, Frank Gadegast
- * Contact : jm@cs.tu-berlin.de, phade@cs.tu-berlin.de
- *
- ************************************************************************
- */
-
- #include "defs.h"
- #include <stdlib.h>
- #include <stdio.h>
- #include <sys/types.h>
- #ifdef DOS
- #include <time.h>
- #else
- #include <sys/time.h>
- #endif
- #include "decode.h"
-
- /* ------ PUBLIC ------ */
-
- int DecodeFrame(int);
- int GetnBit(int);
- int GetBit();
- void bytealign();
-
- /* ------ PRIVAT ------ */
-
- static void SetCTableEntry();
- static void DecompressMDU(int);
- static void DecodeDFrame();
- static void DecodeAC(INT,INT *);
- static void CBPDecodeAC(INT,INT *);
- static INT DecodeDC(DHUFF *);
-
- /* ------ IMPORT ------ */
-
- extern void ReadHeaderTrailer(); /* header.c */
- extern void ReadSliceHeader();
- extern int ReadMakroblockHeader();
-
- extern INT Decode(DHUFF *); /* huff.c */
-
- /* ------ VARS ------ */
-
- static unsigned long frame_buffer_pos = 0;
-
- static INT current_read_byte = 0;
- static INT read_position = 0;
- static int c_table_entries = 0;
- static short last_makroblock = 0;
-
- /* ------ IMPORT ------ */
-
- extern INT bit_set_mask[]; /* stream.c */
- extern BYTE *frame_buffer;
-
- extern SECURETABLE c_table[]; /* main.c */
-
- extern DHUFF *DCLumDHuff; /* huff.c */
- extern DHUFF *DCChromDHuff;
- extern DHUFF *T1DHuff;
- extern DHUFF *T2DHuff;
-
- extern int current_makroblock; /* header */
- extern int PType; /* group of pictures */
- extern int SQuant;
-
- extern int MType; /* makroblock layer */
- extern int LastMType;
- extern int MQuant;
- extern int SVP;
- extern int MVD1H;
- extern int MVD1V;
- extern int MVD2H;
- extern int MVD2V;
- extern int LastMVD1H;
- extern int LastMVD1V;
- extern int LastMVD2H;
- extern int LastMVD2V;
- extern int CBP;
- extern int MBSRead;
- extern int MBAIncrement;
- extern int LastMBA;
- extern int CurrentMBA;
-
- extern int DCQuantMType[];
- extern int IntraQuantMType[];
- extern int PredQuantMType[];
- extern int InterQuantMType[];
- extern int *QuantPMType[];
-
- extern int IntraMFMType[];
- extern int PredMFMType[];
- extern int InterMFMType[];
- extern int DCMFMType[];
- extern int *MFPMType[];
-
- extern int IntraMBMType[];
- extern int PredMBMType[];
- extern int InterMBMType[];
- extern int DCMBMType[];
- extern int *MBPMType[];
-
-
- extern int IntraCBPMType[];
- extern int PredCBPMType[];
- extern int InterCBPMType[];
- extern int DCCBPMType[];
- extern int *CBPPMType[];
-
- extern int IntraIMType[];
- extern int PredIMType[];
- extern int InterIMType[];
- extern int DCIMType[];
- extern int *IPMType[];
-
-
- int DecodeFrame(int mode)
- {
- INT x;
- INT OldType,OldMVD1V,OldMVD1H,OldMVD2V,OldMVD2H;
- INT NextType,NextMVD1V,NextMVD1H,NextMVD2V,NextMVD2H,NextCBP;
- INT NextMBA,NextVPos;
- INT StartSlice,LastPass=0;
- int temp;
- unsigned long offset = 0;
-
- #ifdef DEBUG
- fprintf(stderr,"%s : %d\n","DecodeFrame",frame_count++);
- #endif
-
- /* offset = lΣnge des PictureHeaders */
- offset = 4;
- /* LΣnge des Markers */
-
- do
- {
-
- temp = frame_buffer[offset] + frame_buffer[offset+1] + frame_buffer[offset+2] + frame_buffer[offset+3];
-
- offset++;
- }
- while(temp != 0x02);
- offset += 3; /* 4 */
-
-
- c_table_entries = 0;
- frame_buffer_pos = 0;
- c_table[0].Offset = 0;
- c_table[0].Len = 8;
-
- MBSRead = 0;
- SVP = 1;
- CBP = 0x3f;
- current_read_byte = 0;
- read_position = -1;
-
- frame_buffer_pos = offset;
- current_makroblock = 0;
- last_makroblock = 0;
-
-
- /* end initialisation */
-
-
- if (PType==P_DCINTRA)
- DecodeDFrame();
-
- CurrentMBS=0;
- CurrentMBA=LastMBA= -1;
- HPos=LastMType= -1;
- VPos=0;
- while(TRUE)
- {
- if (MBSRead >= 0)
- {
-
- ReadSliceHeader();
- CurrentMBS++;
- NextVPos = SVP-1;
- }
- else
- {
- NextMBA = MBHeight*MBWidth-1;
- if (CurrentMBA >= NextMBA) break;
- LastPass=1;
- NextMBA++;
- }
-
- MVD1H=MVD1V=MVD2H=MVD2V=0;
- UseQuant=SQuant;
- if (VPos > MBHeight)
- {
- #ifdef DEBUG
- fprintf(stderr,"VPos: %d MBHeight: %d. Buffer Overflow\n",VPos,MBHeight);
- #endif
- return(0);
- }
- for(x=0;x<3;x++) LastDC[x]=128;
- StartSlice=1;
- while(TRUE)
- {
- OldType=MType;
- OldMVD1V=MVD1V; OldMVD1H=MVD1H;
- OldMVD2V=MVD2V; OldMVD2H=MVD2H;
- if (StartSlice) MVD1H=MVD1V=MVD2H=MVD2V=0;
- if (!LastPass)
- {
- if (ReadMakroBlockHeader()) break;
- if (StartSlice)
- {
- StartSlice=0;
- NextMBA = NextVPos*MBWidth+MBAIncrement-1;
- }
- else
- NextMBA = LastMBA + MBAIncrement;
- }
- else
- {
- #ifdef DEBUG
- fprintf(stderr,"Entering Last Pass: %d of %d\n",
- CurrentMBA,NextMBA);
- #endif
- if (LastPass++>1) break;
- }
- NextType=MType; NextCBP = CBP;
- NextMVD1V=MVD1V; NextMVD1H=MVD1H;
- NextMVD2V=MVD2V; NextMVD2H=MVD2H;
- while(CurrentMBA < NextMBA)
- {
- CurrentMBA++;
- if (++HPos >= MBWidth)
- {HPos=0; VPos++;}
- if (CurrentMBA < NextMBA)
- {
- switch(PType)
- {
- case P_INTRA:
- #ifdef DEBUG
- fprintf(stderr,"Bad skipped macroblock.\n");
- #endif
- MType=OldType; CBP=0;
- break;
- case P_PREDICTED:
- if (QuantPMType[PType][OldType])
- MType=5;
- else MType=1;
- CBP=0; MVD1V=0;MVD1H=0;
- break;
- case P_INTERPOLATED:
- MType = OldType;
- CBP = 0;
- MVD1V = OldMVD1V; MVD1H = OldMVD1H;
- MVD2V = OldMVD2V; MVD2H = OldMVD2H;
- if (IPMType[PType][MType])
- {
- #ifdef DEBUG
- fprintf(stderr,"Interpolated skipped INTRA macroblock\n");
- #endif
- }
- break;
- }
- }
- else if (LastPass) break;
- else
- {
- MType=NextType;CBP=NextCBP;
- MVD1V=NextMVD1V;MVD1H=NextMVD1H;
- MVD2V=NextMVD2V;MVD2H=NextMVD2H;
- }
-
- DecompressMDU(mode);
- }
- LastMType = MType;
- LastMBA = CurrentMBA;
- }
- if (MBSRead<0) break;
- else ReadHeaderTrailer();
- }
-
- return(c_table_entries);
- }
-
-
- static void SetCTableEntry()
- {
-
- switch(MType)
- {
- case 0 :/* P_INTRA */ /* break; */
- case 3 :/* P_PREDICTED */
- if(last_makroblock != current_makroblock)
- {
-
- last_makroblock = current_makroblock;
- if((c_table[c_table_entries].Offset + c_table[c_table_entries].Len + 7) >= (short)frame_buffer_pos)
- {
- c_table[c_table_entries].Len = (short)frame_buffer_pos - c_table[c_table_entries].Offset;
- }
- else
- {
- c_table_entries++;
- c_table[c_table_entries].Offset = (short)frame_buffer_pos;
- c_table[c_table_entries].Len = 0;
- }
- }
- else
- {
- c_table[c_table_entries].Len = (short)frame_buffer_pos - c_table[c_table_entries].Offset;
- }
-
- case 6 :break;
- default:break;
- }
-
- }
-
-
- static void DecompressMDU(int mode)
- {
-
- INT c,j,x;
- INT *input;
-
- #ifdef CODEC_DEBUG
- fprintf(stderr,"%s : %d\n","DecompressMDU",decode_mdu_count++);
- #endif
- #ifdef MB_DEBUG
- fprintf(stderr,"CMBS: %d CMDU: %d LastDC: %d\n",
- VPos, HPos, LastDC[0]);
- #endif
-
- if (PType==P_PREDICTED)
- {
- if (!MFPMType[PType][MType]) MVD1H=MVD1V=0;
- }
- else if (PType==P_INTERPOLATED)
- {
- if (IPMType[PType][MType]) MVD1H=MVD1V=MVD2H=MVD2V=0;
- }
- if (QuantPMType[PType][MType])
- {
- UseQuant=MQuant; /* Macroblock overrides */
- SQuant=MQuant; /* Overrides for future */
- }
- else UseQuant=SQuant;
- if (IPMType[PType][MType])
- {
- if ((LastMType<0)||!(IPMType[PType][LastMType]))
- for(x=0;x<3;x++) LastDC[x]=128; /* Reset DC prediction */
- } /* if last one wasn't Intra */
-
-
- for(c=0;c<6;c++)
- {
-
- j=BlockJ[c];
- input = mb_buffer;
- if (CBP & bit_set_mask[5-c])
- {
- if (CBPPMType[PType][MType])
- CBPDecodeAC(0,input);
- else
- {
- /* Intra kodierte Makrobl÷cke */
- /* Intra MType 0 */
- /* Predicted 3 */
- /* Interpolated 6 */
-
- SetCTableEntry();
- if (j)
- *input = DecodeDC(DCChromDHuff) + LastDC[j];
- else
- *input = DecodeDC(DCLumDHuff) + LastDC[j];
- LastDC[j] = *input;
- DecodeAC(1,input);
- }
-
- }
- else for(x=0;x<64;x++) input[x]=0;
-
- }
- }
-
-
- static void DecodeDFrame()
- {
- fprintf(stderr," not yet implemented \n");
- error_exit(0);
- }
-
-
-
-
- void DecodeAC(INT index,INT *matrix)
- {
-
- INT k,r,l;
- INT *mptr;
-
- #ifdef CODEC_DEBUG
- fprintf(stderr,"DecodeAC\n");
- #endif
-
- for(mptr=matrix+index;mptr<matrix+BLOCKSIZE;mptr++) {*mptr = 0;}
- for(k=index;k<BLOCKSIZE;)
- {
- r = Decode(T1DHuff);
- {
- #ifdef CC_DEBUG
- fprintf(stderr," r (T1D) %d\n",(int)r);
- #endif
- }
- if (!r)
- {
- #ifdef CODEC_DEBUG
- fprintf(stderr,"Return:%d\n",k);
- #endif
- return;
- } /*Eof*/
- if (r == HUFFMAN_ESCAPE)
- {
- r = GetnBit(6);
- l = GetnBit(8);
- if (l==0x00)
- l = GetnBit(8); /* extended precision */
- else if (l==0x80)
- l = GetnBit(8) | extend_mask[8]; /* extended sign */
- else if (l & bit_set_mask[7])
- l |= extend_mask[7];
- }
- else
- {
- l = r & 0xff;
- r = r >> 8;
- if (GetBit()) {l = -l;}
- }
- #ifdef CC_DEBUG
- fprintf(stderr,"DecodeAC: k:%d r:%d l:%d\n",(int)k,(int)r,(int)l);
- #endif
- k += r;
- if (k>=BLOCKSIZE)
- {
- #ifdef DEBUG
- fprintf(stderr,"k greater than blocksize:\n",k);
- #endif
- fprintf(stderr,"k greater than blocksize:\n",k);
- break;
- }
- matrix[k++] = l;
- NumberNZ++;
- }
- if (r = Decode(T1DHuff))
- {
- #ifdef DEBUG
- fprintf(stderr,"EOB expected, found 0x%x.\n",r);
- #endif
- fprintf(stderr,"EOB expected, found 0x%x.\n",r);
- }
- }
-
- void CBPDecodeAC(INT index,INT *matrix)
- {
-
- INT k,r,l;
- INT *mptr;
-
- #ifdef CODEC_DEBUG
- fprintf(stderr,"CBPDecodeAC\n");
- #endif
-
- for(mptr=matrix+index;mptr<matrix+BLOCKSIZE;mptr++) {*mptr = 0;}
- k = index;
- r = Decode(T2DHuff);
- if (!r)
- {
- #ifdef DEBUG
- fprintf(stderr,"Bad EOF in CBP block.\n");
- #endif
- fprintf(stderr,"Bad EOF in CBP block.\n");
- return;
- }
- if (r==HUFFMAN_ESCAPE)
- {
- r = (INT)GetnBit(6);
- l = (INT)GetnBit(8);
- if (l==0x00)
- {
- l = (INT)GetnBit(8); /* extended precision */
- }
- else if (l==0x80)
- {
- l = (INT)GetnBit(8) | extend_mask[8]; /* extended sign */
- }
- else if (l & bit_set_mask[7])
- {
- l |= extend_mask[7];
- }
- }
- else
- {
- l = r & 0xff;
- r = r >> 8;
- if (GetBit()) {l = -l;}
- }
- k += r;
- matrix[k++] = l;
- NumberNZ++;
- while(k<BLOCKSIZE)
- {
- r = Decode(T1DHuff);
- if (!r) {return;} /*Eof*/
- if (r == HUFFMAN_ESCAPE)
- {
- r = GetnBit(6);
- l = GetnBit(8);
- if (l==0x00)
- {
- l = (INT)GetnBit(8); /* extended precision */
- }
- else if (l==0x80)
- {
- l = (INT)GetnBit(8) | extend_mask[8]; /* extended sign */
- }
- else if (l & bit_set_mask[7])
- {
- l |= extend_mask[7];
- }
- }
- else
- {
- l = r & 0xff;
- r = r >> 8;
- if (GetBit()) {l = -l;}
- }
-
- #ifdef CC_DEBUG
- fprintf(stderr,"CBPDecodeAC: k:%d r:%d l:%d\n",r,l);
- #endif
-
- if (l & bit_set_mask[7])
- l |= extend_mask[7];
- k += r;
- if (k>=BLOCKSIZE)
- {
- #ifdef CODEC_DEBUG
- fprintf(stderr,"k greater than blocksize:\n",k);
- #endif
- break;
- }
- matrix[k++] = l;
- NumberNZ++;
- }
- if (r = Decode(T1DHuff))
- {
- #ifdef DEBUG
- fprintf(stderr,"EOB expected, found 0x%x.\n",r);
- #endif
- }
- }
-
- INT DecodeDC(DHUFF *LocalDHuff)
- {
-
- INT s,diff;
-
- s = Decode(LocalDHuff);
-
- #ifdef CODEC_DEBUG
- fprintf(stderr,"DecodeDC\n");
- #endif
- #ifdef CC_DEBUG
- fprintf(stderr,"DC Decode sig. %d\n",s);
- #endif
-
- if (s)
- {
- diff = GetnBit(s);
- s--;
-
- #ifdef CC_DEBUG
- fprintf(stderr,"Raw DC Decode %d\n",diff);
- #endif
- if ((diff & bit_set_mask[s]) == 0)
- {
- diff |= extend_mask[s];
- diff++;
- }
- }
- else
- diff=0;
-
- return(diff);
- }
-
- void bytealign()
- {
- current_read_byte = 0;
- read_position = -1;
- frame_buffer_pos = 0;
- }
-
- int GetBit()
- {
- if (read_position<0)
- {
- current_read_byte= (INT)frame_buffer[frame_buffer_pos++];
- read_position = 7;
- }
- if (current_read_byte&bit_set_mask[read_position--]) {return(1);}
- return(0);
- }
-
-
- int GetnBit(int nbits)
- {
- int b=0;
-
- while(nbits--)
- {
- b <<= 1;
- if (GetBit()) {b |= 1;}
- }
- return(b);
- }
-
-
-
-
-
-