📄 decoder.cpp
字号:
/*************************************************************************
This software module was originally developed by
Ming-Chieh Lee (mingcl@microsoft.com), Microsoft Corporation
Wei-ge Chen (wchen@microsoft.com), Microsoft Corporation
Bruce Lin (blin@microsoft.com), Microsoft Corporation
Chuang Gu (chuanggu@microsoft.com), Microsoft Corporation
(date: March, 1996)
and edited by
Hiroyuki Katata (katata@imgsl.mkhar.sharp.co.jp), Sharp Corporation
Norio Ito (norio@imgsl.mkhar.sharp.co.jp), Sharp Corporation
Shuichi Watanabe (watanabe@imgsl.mkhar.sharp.co.jp), Sharp Corporation
(date: October, 1997)
and also edited by
Dick van Smirren (D.vanSmirren@research.kpn.com), KPN Research
Cor Quist (C.P.Quist@research.kpn.com), KPN Research
(date: July, 1998)
in the course of development of the MPEG-4 Video (ISO/IEC 14496-2).
This software module is an implementation of a part of one or more MPEG-4 Video tools
as specified by the MPEG-4 Video.
ISO/IEC gives users of the MPEG-4 Video free license to this software module or modifications
thereof for use in hardware or software products claiming conformance to the MPEG-4 Video.
Those intending to use this software module in hardware or software products are advised that its use may infringe existing patents.
The original developer of this software module and his/her company,
the subsequent editors and their companies,
and ISO/IEC have no liability for use of this software module or modifications thereof in an implementation.
Copyright is not released for non MPEG-4 Video conforming products.
Sharp retains full right to use the code for his/her own purpose,
assign or donate the code to a third party and to inhibit third parties from using the code for non <MPEG standard> conforming products.
This copyright notice must be included in all copies or derivative works.
Copyright (c) 1997.
Module Name:
tps_decoder.cpp
Abstract:
caller for decoder for temporal scalability
Revision History:
*************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
#include <fstream.h>
#ifdef __PC_COMPILER_
#include <windows.h>
#include <mmsystem.h>
#endif // __PC_COMPILER_
#include "typeapi.h"
#include "mode.hpp"
#include "vopses.hpp"
#include "entropy/bitstrm.hpp"
#include "tps_enhcbuf.hpp"
#include "decoder/enhcbufdec.hpp"
#include "decoder/vopsedec.hpp"
#include "dataStruct.hpp"
#ifndef __GLOBAL_VAR_
#define __GLOBAL_VAR_
#endif
#include "global.hpp"
#ifdef __MFC_
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
#define new DEBUG_NEW
#endif // __MFC_
Void dumpFrame (const CVOPU8YUVBA* pvopcQuant, FILE* pfYUV, FILE* pfSeg, AlphaUsage, CRct& rct, UInt nBits, Int iAlphaScale, Int DumpSkip);
#define MAX_TIME 99999 // for bitstreams stopped at BVOP
#define USAGE "Usage: \tDECODER bitstream_file [enhn_layer_bitstream_file] output_file width height\n\
or: \tDECODER -vtc bitstream_file output_file target_spatial_layer target_snr_layer\n"
// Main Routine
int main(int argc, char* argv[])
{
Bool bScalability = 0;
Bool bWavelet = 0;
Bool main_short_video_header; // Added by KPN for short headers [FDS]
main_short_video_header = FALSE;
if(argc>1 && strcmp(argv[1],"-vtc")==0)
{
bWavelet = 1;
if(argc != 6)
{
fprintf(stderr,USAGE);
exit(1);
}
}
else
{
if (argc < 5 || argc > 6) {
fprintf (stderr,USAGE);
exit(1);
}
else if (argc == 6)
bScalability = 1;
}
FILE *pfBits;
if ((pfBits = fopen (argv [bWavelet + 1], "rb")) == NULL )
fatal_error("Bitstream File Not Found");
fclose (pfBits);
if (bScalability) {
if ((pfBits = fopen (argv [2], "rb")) == NULL )
fatal_error("Bitstream File for Enhancement Layer Not Found\n");
fclose (pfBits);
}
if(bWavelet)
{
///// WAVELET VTC: begin /////////////////////////
CVTCDecoder vtcdec;
// start VTC decoding
// argv[1]: "-vtc"
// argv[2]: bitstream file
// argv[3]: decoded image file
// argv[4]: target spatial layer
// argv[5]: target SNR layer
vtcdec.decode(argv[2], argv[3], atoi(argv[4]), atoi(argv[5]) );
return 0;
/////// WAVELET VTC: end /////////////////////////
}
CRct rctDisplay (0, 0, atoi (argv [3 + bScalability]), atoi (argv [4 + bScalability]));
/*Added */
CRct rctDisplay_SSenh (0, 0, atoi (argv [3 + bScalability]), atoi (argv [4 + bScalability]));
Bool bTemporalScalability = 0;
if (bScalability){
CVideoObjectDecoder* pvodec_tps[2];
cout << "Checking scalability type...\n";
pvodec_tps[BASE_LAYER] = new CVideoObjectDecoder (argv[1], rctDisplay.width, rctDisplay.height (), NULL, &main_short_video_header);
pvodec_tps[ENHN_LAYER] = new CVideoObjectDecoder (argv[2], rctDisplay.width, rctDisplay.height (), NULL, &main_short_video_header);
pvodec_tps[BASE_LAYER]->setClockRateScale( pvodec_tps[ENHN_LAYER] ); // added by Sharp (98/6/26)
Time FirstBase = pvodec_tps[BASE_LAYER] -> senseTime ();
Time FirstEnhn = pvodec_tps[ENHN_LAYER] -> senseTime ();
if ( FirstBase != FirstEnhn ){
bTemporalScalability = 1;
cout << "Starting temporal scalability decoding...\n\n";
}
else{
bTemporalScalability = 0;
cout << "Starting spatial scalability decoding...\n\n";
}
delete pvodec_tps[BASE_LAYER];
delete pvodec_tps[ENHN_LAYER];
}
if ( !bScalability || !bTemporalScalability ){
CVideoObjectDecoder* pvodec [2];
Bool bSpatialScalable = FALSE;
//CRct rctDisplayBackup = rctDisplay; // for recovery from sprite decoding
pvodec [BASE_LAYER] = new CVideoObjectDecoder (argv [1], rctDisplay.width, rctDisplay.height(), &bSpatialScalable, &main_short_video_header);
// NBIT: get nBits information
UInt nBits = pvodec [BASE_LAYER]->volmd ().nBits;
/* Added*/
if (bScalability){
pvodec [ENHN_LAYER] = new CVideoObjectDecoder (argv [2], rctDisplay.width, rctDisplay.height(), &bSpatialScalable, &main_short_video_header);
/*Added*/
if(bSpatialScalable)
pvodec[ENHN_LAYER]->set_enh_display_size(rctDisplay, &rctDisplay_SSenh);
}
if (pvodec [BASE_LAYER] -> fSptUsage () == 1) {
// decode the initial sprite: //wchen: instead of calling decode ()
pvodec [BASE_LAYER] -> decodeInitSprite ();
}
FILE* pfReconYUV [2];
Char pchTmp [100];
sprintf (pchTmp, "%s.yuv", argv [2 + bScalability]);
pfReconYUV [BASE_LAYER] = fopen (pchTmp, "wb");
fatal_error("cant open output yuv file",pfReconYUV [BASE_LAYER] != NULL);
if (bScalability) {
sprintf (pchTmp, "%s_e.yuv", argv [2 + bScalability]);
pfReconYUV [ENHN_LAYER]= fopen (pchTmp, "wb");
fatal_error("cant open enhancement layer output yuv file",pfReconYUV [ENHN_LAYER] != NULL);
}
sprintf (pchTmp, "%s.seg", argv [2 + bScalability]);
FILE* pfReconSeg = NULL;
if (pvodec [BASE_LAYER]-> volmd ().fAUsage != RECTANGLE) {
pfReconSeg = fopen (pchTmp, "wb");
fatal_error("cant open output seg file",pfReconSeg != NULL);
}
Int iEof = 1;
Int nFrames = 0;
const CVOPU8YUVBA* pvopcQuant;
#ifdef __PC_COMPILER_
Int tickBegin = ::GetTickCount ();
#endif // __PC_COMPILER_
Bool bCachedRefFrame = FALSE;
Bool bCachedRefFrameCoded = FALSE;
while (iEof != EOF)
{
if (main_short_video_header) // Added by KPN for short headers
{
fprintf(stderr,"Frame number: %d\n", nFrames);
iEof = pvodec [BASE_LAYER] -> h263_decode ();
}
else
iEof = pvodec [BASE_LAYER] -> decode ();
if (iEof != EOF)
nFrames++;
if(pvodec [BASE_LAYER] -> fSptUsage () == 1)
{
// sprite
if(iEof != EOF)
{
pvopcQuant = pvodec [BASE_LAYER]->pvopcReconCurr();
dumpFrame (pvopcQuant, pfReconYUV [BASE_LAYER], pfReconSeg, pvodec[BASE_LAYER]->volmd().fAUsage, rctDisplay,
nBits, pvodec [BASE_LAYER]->vopmd().iVopConstantAlphaValue, 0);
}
}
else
{
if(iEof == EOF)
{
// dump final cached frame if present
if(bCachedRefFrame)
{
bCachedRefFrame = FALSE;
if(bCachedRefFrameCoded)
{
pvopcQuant = pvodec [BASE_LAYER]->pvopcRefQLater(); // future reference
dumpFrame (pvopcQuant, pfReconYUV [BASE_LAYER], pfReconSeg, pvodec[BASE_LAYER]->volmd().fAUsage, rctDisplay,
nBits, pvodec [BASE_LAYER]->vopmd().iVopConstantAlphaValue, 0);
}
else // non coded
dumpNonCodedFrame(pfReconYUV [BASE_LAYER], pfReconSeg, rctDisplay, nBits);
}
}
else
{
// dump if bvop
if(pvodec[BASE_LAYER]->vopmd().vopPredType == BVOP)
{
// BVOP
if(iEof != FALSE)
{
pvopcQuant = pvodec [BASE_LAYER]->pvopcReconCurr(); // current vop
dumpFrame (pvopcQuant, pfReconYUV [BASE_LAYER], pfReconSeg, pvodec[BASE_LAYER]->volmd().fAUsage, rctDisplay,
nBits, pvodec [BASE_LAYER]->vopmd().iVopConstantAlphaValue, 0);
}
else // non coded BVOP
dumpNonCodedFrame(pfReconYUV [BASE_LAYER], pfReconSeg, rctDisplay, nBits);
}
else
{
// not a BVOP, so dump any previous cached frame
if(bCachedRefFrame)
{
bCachedRefFrame = FALSE;
if(bCachedRefFrameCoded)
{
pvopcQuant = pvodec [BASE_LAYER]->pvopcRefQPrev(); // past reference
dumpFrame (pvopcQuant, pfReconYUV [BASE_LAYER], pfReconSeg, pvodec[BASE_LAYER]->volmd().fAUsage, rctDisplay,
nBits, pvodec [BASE_LAYER]->vopmd().iVopConstantAlphaValue, 0);
}
else // non coded
dumpNonCodedFrame(pfReconYUV [BASE_LAYER], pfReconSeg, rctDisplay, nBits);
}
// cache current reference
bCachedRefFrame = TRUE;
bCachedRefFrameCoded = (iEof != FALSE);
}
}
}
if (bSpatialScalable == TRUE) {
// if base layer is non coded, pvopcQuant=NULL, but enh layer should also be non coded.
if(iEof == FALSE)
pvopcQuant = NULL;
else
pvopcQuant = pvodec [BASE_LAYER]->pvopcReconCurr();
iEof = pvodec [ENHN_LAYER] -> decode (pvopcQuant);
if(iEof!=EOF)
nFrames++; // include enhancement layer
if(iEof==FALSE)
dumpNonCodedFrame(pfReconYUV [ENHN_LAYER], NULL, rctDisplay_SSenh, nBits);
/* dumpNonCodedFrame(pfReconYUV [ENHN_LAYER], NULL, rctDisplay * 2, nBits);*/
if (iEof != EOF && iEof!=FALSE)
/*Added*/
dumpFrame (pvodec [ENHN_LAYER]->pvopcReconCurr (), pfReconYUV [ENHN_LAYER], NULL, RECTANGLE, rctDisplay_SSenh,
nBits, pvodec [BASE_LAYER]->vopmd().iVopConstantAlphaValue, 0); // still base layer
/*
dumpFrame (pvodec [ENHN_LAYER]->pvopcReconCurr (), pfReconYUV [ENHN_LAYER], NULL, RECTANGLE, rctDisplay * 2,
nBits, pvodec [BASE_LAYER]->vopmd().iVopConstantAlphaValue, 0); // still base layer
*/
}
}
#ifdef __PC_COMPILER_
Int tickAfter = ::GetTickCount ();
printf ("Total time: %d\n", tickAfter - tickBegin);
Double dAverage = (Double) (tickAfter - tickBegin) / (Double) (nFrames);
printf ("Total frames: %d\tAverage time: %.6lf\n", nFrames, dAverage);
printf ("FPS %.6lf\n", 1000.0 / dAverage);
#endif // __PC_COMPILER_
fclose (pfReconYUV [BASE_LAYER]);
if (pvodec [BASE_LAYER]->volmd ().fAUsage != RECTANGLE)
fclose (pfReconSeg);
delete pvodec [BASE_LAYER];
if (bScalability) {
fclose (pfReconYUV [ENHN_LAYER]);
delete pvodec [ENHN_LAYER];
}
}
else { // loop for temporal scalability
CVideoObjectDecoder* pvodec[2];
pvodec[BASE_LAYER] = new CVideoObjectDecoder (argv[1], rctDisplay.width, rctDisplay.height (), NULL, &main_short_video_header); // modified by Sharp (98/7/16)
UInt nBits = pvodec [BASE_LAYER]->volmd ().nBits; // added by Sharp (98/11/11)
if(bScalability){
pvodec[ENHN_LAYER] = new CVideoObjectDecoder (argv[2], rctDisplay.width, rctDisplay.height (), NULL, &main_short_video_header); // modified by Sharp (98/7/16)
// for back/forward shape
pvodec[ENHN_LAYER]->rgpbfShape[0] = new CVideoObjectDecoder (rctDisplay.width, rctDisplay.height ());
pvodec[ENHN_LAYER]->rgpbfShape[1] = new CVideoObjectDecoder (rctDisplay.width, rctDisplay.height ());
pvodec[BASE_LAYER]->setClockRateScale( pvodec[ENHN_LAYER] );
// copy pointers
pvodec[ENHN_LAYER]->copyTobfShape ();
}
Char pchTmp [100];
FILE* pfReconYUV [2]; // following two lines are swapped by Sharp (98/10/26)
#ifndef __OUT_ONE_FRAME_
sprintf (pchTmp, "%s.yuv", argv [2 + bScalability]);
pfReconYUV [BASE_LAYER] = fopen (pchTmp, "wb");
fatal_error("cant open output yuv file",pfReconYUV [BASE_LAYER] != NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -