354 lines
9.7 KiB
C
354 lines
9.7 KiB
C
/* File: sv_h261_marker.c */
|
|
/*****************************************************************************
|
|
** Copyright (c) Digital Equipment Corporation, 1995, 1997 **
|
|
** **
|
|
** All Rights Reserved. Unpublished rights reserved under the copyright **
|
|
** laws of the United States. **
|
|
** **
|
|
** The software contained on this media is proprietary to and embodies **
|
|
** the confidential technology of Digital Equipment Corporation. **
|
|
** Possession, use, duplication or dissemination of the software and **
|
|
** media is authorized only pursuant to a valid written license from **
|
|
** Digital Equipment Corporation. **
|
|
** **
|
|
** RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure by the U.S. **
|
|
** Government is subject to restrictions as set forth in Subparagraph **
|
|
** (c)(1)(ii) of DFARS 252.227-7013, or in FAR 52.227-19, as applicable. **
|
|
******************************************************************************/
|
|
/*************************************************************
|
|
This file contains most of the marker information.
|
|
*************************************************************/
|
|
|
|
/*
|
|
#define _VERBOSE_
|
|
*/
|
|
|
|
/*LABEL marker.c */
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "sv_intrn.h"
|
|
#include "SC.h"
|
|
#include "SC_err.h"
|
|
#include "sv_h261.h"
|
|
#include "proto.h"
|
|
#include "sv_proto.h"
|
|
#include "h261.h"
|
|
|
|
/*PRIVATE*/
|
|
/*extern int TemporalReference;
|
|
extern int PType;
|
|
*/
|
|
extern int Type2;
|
|
/*
|
|
extern int MType;
|
|
extern int GQuant;
|
|
extern int MQuant;
|
|
*/
|
|
/*
|
|
extern int MVDH;
|
|
extern int MVDV;
|
|
extern int CBP;
|
|
*/
|
|
/*
|
|
extern int ParityEnable;
|
|
extern int PSpareEnable;
|
|
extern int GSpareEnable;
|
|
extern int Parity;
|
|
extern int PSpare;
|
|
extern int GSpare;
|
|
extern int GRead;
|
|
extern int MBA;
|
|
extern int LastMBA;
|
|
|
|
extern int LastMVDV;
|
|
extern int LastMVDH;
|
|
|
|
extern int LastMType;
|
|
*/
|
|
extern int QuantMType[];
|
|
extern int CBPMType[];
|
|
extern int MFMType[];
|
|
|
|
|
|
extern int extend_mask[];
|
|
|
|
|
|
const int bit_set_mask[] =
|
|
{0x00000001,0x00000002,0x00000004,0x00000008,
|
|
0x00000010,0x00000020,0x00000040,0x00000080,
|
|
0x00000100,0x00000200,0x00000400,0x00000800,
|
|
0x00001000,0x00002000,0x00004000,0x00008000,
|
|
0x00010000,0x00020000,0x00040000,0x00080000,
|
|
0x00100000,0x00200000,0x00400000,0x00800000,
|
|
0x01000000,0x02000000,0x04000000,0x08000000,
|
|
0x10000000,0x20000000,0x40000000,0x80000000};
|
|
|
|
/*
|
|
** Function: WritePictureHeader()
|
|
** Purpose: Writes the header of picture out to the stream.
|
|
** One of these is necessary before every frame is transmitted.
|
|
*/
|
|
void WritePictureHeader(SvH261Info_t *H261, ScBitstream_t *bs)
|
|
{
|
|
sc_vprintf("WritePictureHeader()\n");
|
|
ScBSPutBits(bs, H261_PICTURE_START_CODE, H261_PICTURE_START_CODE_LEN);
|
|
ScBSPutBits(bs, H261->TemporalReference, 5);
|
|
ScBSPutBits(bs, H261->PType, 6);
|
|
if (H261->PSpareEnable)
|
|
{
|
|
ScBSPutBit(bs, 1);
|
|
ScBSPutBits(bs, H261->PSpare, 8);
|
|
}
|
|
ScBSPutBit(bs, 0);
|
|
}
|
|
|
|
|
|
/*
|
|
** Function: ReadPictureHeader()
|
|
** Purpose: Reads the header off of the stream. It assumes that the
|
|
** first PSC has already been read in. (Necessary to tell the
|
|
** difference between a new picture and another GOB.)
|
|
*/
|
|
void ReadPictureHeader(SvH261Info_t *H261, ScBitstream_t *bs)
|
|
{
|
|
sc_vprintf ("ReadPictureHeader \n");
|
|
|
|
H261->TemporalReference = (int) ScBSGetBits(bs,5);
|
|
|
|
H261->PType = (int)ScBSGetBits(bs,6);
|
|
for(H261->PSpareEnable = 0;ScBSGetBit(bs);)
|
|
{
|
|
H261->PSpareEnable=1;
|
|
H261->PSpare = (int)ScBSGetBits(bs,8);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
** Function: WriteGOBHeader()
|
|
** Purpose: Writes a GOB out to the stream.
|
|
*/
|
|
void WriteGOBHeader(SvH261Info_t *H261, ScBitstream_t *bs)
|
|
{
|
|
sc_vprintf("WriteGOBHeader()\n");
|
|
|
|
ScBSPutBits(bs, H261_GOB_START_CODE, H261_GOB_START_CODE_LEN);
|
|
ScBSPutBits(bs, H261->GRead+1, 4);
|
|
ScBSPutBits(bs, H261->GQuant, 5);
|
|
if (H261->GSpareEnable)
|
|
{
|
|
ScBSPutBit(bs, 1);
|
|
ScBSPutBits(bs, H261->GSpare, 8);
|
|
}
|
|
ScBSPutBit(bs, 0);
|
|
}
|
|
|
|
|
|
/*
|
|
** Function: ReadHeaderTrailer()
|
|
** Purpose: Reads the trailer of the PSC or H261_GOB_START_CODE code. It is
|
|
** used to determine whether it is just a GOB or a new picture.
|
|
*/
|
|
void ReadHeaderTrailer(SvH261Info_t *H261, ScBitstream_t *bs)
|
|
{
|
|
sc_vprintf("ReadHeaderTrailer \n");
|
|
|
|
H261->GRead = (int)ScBSGetBits(bs, 4)-1;
|
|
}
|
|
|
|
/*
|
|
** Function: ReadHeaderHeader()
|
|
** Purpose: Reads the header header off of the stream. This is
|
|
** a precursor to the GOB read or the PSC read.
|
|
** Return: -1 on error
|
|
*/
|
|
SvStatus_t ReadHeaderHeader(SvH261Info_t *H261, ScBitstream_t *bs)
|
|
{
|
|
int input;
|
|
|
|
sc_vprintf("ReadHeaderHeader\n");
|
|
|
|
input = (int)ScBSPeekBits(bs, H261_GOB_START_CODE_LEN);
|
|
if (input != H261_GOB_START_CODE)
|
|
{
|
|
if (!ScBSSeekStopBefore(bs, H261_GOB_START_CODE, H261_GOB_START_CODE_LEN))
|
|
{
|
|
sc_dprintf("Illegal GOB Start Code. Read: %d\n",input);
|
|
return(SvErrorIllegalGBSC);
|
|
}
|
|
}
|
|
input = (int)ScBSGetBits(bs, H261_GOB_START_CODE_LEN);
|
|
return(NoErrors);
|
|
}
|
|
|
|
|
|
/*
|
|
** Function: ReadGOBHeader()
|
|
** Purpose: Reads the GOB information off of the stream. We assume
|
|
** that the first bits have been read in by ReadHeaderHeader...
|
|
** or some such routine.
|
|
*/
|
|
void ReadGOBHeader(SvH261Info_t *H261, ScBitstream_t *bs)
|
|
{
|
|
sc_vprintf("ReadGOBHeader()\n");
|
|
|
|
H261->GQuant =(int)ScBSGetBits(bs,5);
|
|
for(H261->GSpareEnable=0; ScBSGetBit(bs);)
|
|
{
|
|
H261->GSpareEnable = 1;
|
|
H261->GSpare = (int)ScBSGetBits(bs,8);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Function: WriteMBHeader()
|
|
** Purpose: Writes a macro-block out to the stream.
|
|
*/
|
|
SvStatus_t WriteMBHeader(SvH261Info_t *H261, ScBitstream_t *bs)
|
|
{
|
|
|
|
int TempH,TempV;
|
|
ScBSPosition_t Start;
|
|
sc_vprintf("WriteMBHeader()\n");
|
|
|
|
sc_dprintf("\n Macro Block Type is %d and MQuant is %d",
|
|
H261->MType, H261->MQuant);
|
|
Start=ScBSBitPosition(bs); /* Start=swtellb(H261); */
|
|
if (!sv_H261HuffEncode(H261,bs,H261->MBA,H261->MBAEHuff))
|
|
{
|
|
sc_dprintf("Attempting to write an empty Huffman code.\n");
|
|
return (SvErrorEmptyHuff);
|
|
|
|
}
|
|
if (!sv_H261HuffEncode(H261,bs,H261->MType,H261->T3EHuff))
|
|
{
|
|
sc_dprintf("Attempting to write an empty Huffman code.\n");
|
|
return (SvErrorEmptyHuff);
|
|
|
|
}
|
|
if (QuantMType[H261->MType])
|
|
ScBSPutBits(bs, H261->MQuant, 5); /* mputvb(H261, 5, H261->MQuant); */
|
|
|
|
H261->NumberBitsCoded=0;
|
|
if (MFMType[H261->MType])
|
|
{
|
|
if ((!MFMType[H261->LastMType])||(H261->MBA!=1)||
|
|
(H261->LastMBA==-1)||(H261->LastMBA==10)||(H261->LastMBA==21))
|
|
{
|
|
if (!sv_H261HuffEncode(H261,bs,(H261->MVDH&0x1f),H261->MVDEHuff)||
|
|
!sv_H261HuffEncode(H261,bs,(H261->MVDV&0x1f),H261->MVDEHuff))
|
|
{
|
|
sc_dprintf("Cannot encode motion vectors.\n");
|
|
return (SvErrorEncodingMV);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TempH = H261->MVDH - H261->LastMVDH;
|
|
if (TempH < -16) TempH += 32;
|
|
if (TempH > 15) TempH -= 32;
|
|
TempV = H261->MVDV - H261->LastMVDV;
|
|
if (TempV < -16) TempV += 32;
|
|
if (TempV > 15) TempV -= 32;
|
|
if (!sv_H261HuffEncode(H261,bs,TempH&0x1f,H261->MVDEHuff)||
|
|
!sv_H261HuffEncode(H261,bs,TempV&0x1f,H261->MVDEHuff))
|
|
{
|
|
sc_dprintf("Cannot encode motion vectors.\n");
|
|
return (SvErrorEncodingMV);
|
|
}
|
|
}
|
|
H261->LastMVDV = H261->MVDV;
|
|
H261->LastMVDH = H261->MVDH;
|
|
}
|
|
else
|
|
{
|
|
H261->LastMVDV=H261->LastMVDH=H261->MVDV=H261->MVDH=0; /* Redundant in most cases */
|
|
}
|
|
|
|
H261->MotionVectorBits+=H261->NumberBitsCoded;
|
|
if (CBPMType[H261->MType])
|
|
{
|
|
if (!sv_H261HuffEncode(H261,bs,H261->CBP,H261->CBPEHuff))
|
|
{
|
|
sc_dprintf("CBP write error\n");
|
|
return (SvErrorCBPWrite);
|
|
}
|
|
}
|
|
H261->Current_MBBits = ScBSBitPosition(bs)-Start; /* (swtellb(H261)-Start); */
|
|
H261->MacroAttributeBits+=H261->Current_MBBits ;
|
|
return (NoErrors);
|
|
|
|
}
|
|
|
|
/*
|
|
** Function: ReadMBHeader()
|
|
** Purpose: Reads the macroblock header from the stream.
|
|
*/
|
|
int ReadMBHeader(SvH261Info_t *H261, ScBitstream_t *bs)
|
|
{
|
|
DHUFF *huff = H261->MBADHuff;
|
|
register unsigned short cb;
|
|
register int State, temp;
|
|
|
|
do {
|
|
DecodeHuff(bs, huff, State, cb, temp);
|
|
} while (State == 34 && ! bs->EOI); /* Get rid of stuff bits */
|
|
H261->MBA = State;
|
|
if (H261->MBA == 35 || bs->EOI)
|
|
return(-1); /* Start of Picture Headers */
|
|
|
|
H261->LastMType = H261->MType;
|
|
huff = H261->T3DHuff;
|
|
DecodeHuff(bs, huff, State, cb, temp);
|
|
H261->MType = State;
|
|
if (QuantMType[H261->MType])
|
|
H261->MQuant = (int)ScBSGetBits(bs,5);
|
|
huff = H261->MVDDHuff;
|
|
if (MFMType[H261->MType])
|
|
{
|
|
if ((!MFMType[H261->LastMType])||(H261->MBA!=1)||
|
|
(H261->LastMBA==-1)||(H261->LastMBA==10)||(H261->LastMBA==21))
|
|
{
|
|
DecodeHuff(bs, huff, State, cb, temp);
|
|
if (State & bit_set_mask[4])
|
|
H261->MVDH = State | extend_mask[4];
|
|
else
|
|
H261->MVDH = State;
|
|
|
|
DecodeHuff(bs, huff, State, cb, temp);
|
|
if (State & bit_set_mask[4])
|
|
H261->MVDV = State | extend_mask[4];
|
|
else
|
|
H261->MVDV = State;
|
|
}
|
|
else
|
|
{
|
|
DecodeHuff(bs, huff, State, cb, temp);
|
|
if (State & bit_set_mask[4])
|
|
State |= extend_mask[4];
|
|
H261->MVDH += State;
|
|
|
|
DecodeHuff(bs, huff, State, cb, temp);
|
|
if (State & bit_set_mask[4])
|
|
State |= extend_mask[4];
|
|
H261->MVDV += State;
|
|
|
|
if (H261->MVDH < -16) H261->MVDH += 32;
|
|
if (H261->MVDH > 15) H261->MVDH -= 32;
|
|
if (H261->MVDV < -16) H261->MVDV += 32;
|
|
if (H261->MVDV > 15) H261->MVDV -= 32;
|
|
}
|
|
}
|
|
else
|
|
H261->MVDV=H261->MVDH=0; /* Theoretically redundant */
|
|
if (CBPMType[H261->MType])
|
|
{
|
|
huff = H261->CBPDHuff;
|
|
DecodeHuff(bs, huff, State, cb, temp);
|
|
H261->CBP = State;
|
|
}
|
|
return(0);
|
|
}
|
|
|