📄 encodeiff.c
字号:
/*!
************************************************************************
* \file
* encodeiff.c
* \brief
* Implementation of the interim file format, as defined
* in Appendix III of WD-1 (JVT-A003r1).
*
* Instructions for a new release of the Joint Model:
* 1. Remember to update WORKING_DRAFT_MAJOR_NO and WORKING_DRAFT_MINOR_NO
* in defines.h appropriately
* 2. Remember to modify the decoder as well
*
* Instructions for modifications to the interim file format:
* 1. Update INTERIM_FILE_MAJOR_NO and INTERIM_FILE_MINOR_NO
* in defines.h appropriately. It is up to the implementor
* to decide, which modification deserves an update in the major
* version number.
* 2. If you modify one of the box types that are of constant size,
* such as the Parameter Set Box, update the hard-coded size of
* the box appropriately.
*
* Feb 10, 2002:
* Until now, the box header only permits the compact size (32 bits mode),
* and the Data Partition mode is not supported. One segment per file
* is created.
*
* \author
* - Dong Tian <tian@cs.tut.fi>
* - Miska M. Hannuksela <miska.hannuksela@nokia.com>
*
************************************************************************
*/
/*!
************************************************************************
* Tian Dong (Last Updated in June 15, 2002)
* \flowchart of how the output module works:
* main()
* {
* start_sequence()
* {
* SequenceHeader(out)
* {
* initInterimFile()
* }
* }
* initSegmentBox()
* {
* ......
* initAlternateTrackHeaderBox()
* {
* initPictureInformationBox()
* initLayerBox()
* }
* initSwitchPictureBox();
* initAlternateTrackMediaBox();
* }
* loop over pictures in the same segment
* {
* encode_one_frame()
* {
* init_frame()
* update header of AlternateTrackHeaderBox
* initPictureInfo
* while (end_of_frame == FALSE) // loop over slices
* {
* encode_one_slice(&sym)
* {
* start_slice()
* {
* newPayloadInfo
* addOnePayloadInfo
* }
* loop over MB encoding // write the MBData to mem buffer
* terminate_slice() file handle
* {
* updating the payloadInfo
* writing media data to the tmp file
* }
* }
* }
* wrPictureInfo // write pictureInfo & all payloadInfos to a temporary file
* {
* write the pictureInfo header to file
* loop to write every payloadInfo to file
* {
* wrPayloadInfo
* update info about SDU in AlternateTrackInfo Box
* }
* }
* freePictureInfo
* }
* }
* updateAlternateTrackHeaderBox();
* updateAlternateTrackMediaBox();
* updateSegmentBox();
* terminate_sequence()
* {
* TerminateInterimFile( outf )
* {
* wrFileTypeBox( outf );
* wrFileHeaderBox( outf );
* wrContentInfoBox( outf );
* wrAlternateTrackInfoBox( outf );
* wrParameterSetBox( outf );
* wrSegmentBox( outf );
* freeAll
* }
* }
* }
************************************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <memory.h>
#include <malloc.h>
#include "global.h"
#include "mbuffer.h"
#include "encodeiff.h"
#include "rtp.h"
FileTypeBox box_ft;
FileHeaderBox box_fh;
ContentInfoBox box_ci;
AlternateTrackInfoBox box_ati;
ParameterSetBox box_ps;
SegmentBox box_s;
AlternateTrackHeaderBox box_ath;
PictureInformationBox box_pi;
PayloadInfo* pCurrPayloadInfo;
PictureInfo currPictureInfo;
LayerBox box_layr[MAX_LAYER_NUMBER];
SubSequenceBox box_sseq[MAX_LAYER_NUMBER];
AlternateTrackMediaBox box_atm;
SwitchPictureBox box_sp;
int isBigEndian=0;
/*!
************************************************************************
* \brief
* checks if the System is big- or little-endian
* \return
* 0, little-endian
* 1, big-endian
************************************************************************
*/
int testEndian()
{
short s;
byte *p;
p=(byte*)&s;
s=1;
return (*p==0);
}
/*!
************************************************************************
* \brief
* Initiate the File Type Box.
* \return
* 0, if success
* -1, otherwise
************************************************************************
*/
int initFileTypeBox()
{
box_ft.type.size = SIZEOF_BOXTYPE + 12;
box_ft.type.type = BOX_FTYP;
memcpy( box_ft.majorBrand, "jvt ", 4 );
box_ft.jmMajorVersion = WORKING_DRAFT_MAJOR_NO;
box_ft.jmMinorVersion = WORKING_DRAFT_MINOR_NO;
box_ft.numCompatibleBrands = 1;
box_ft.compatibleBrands = calloc( box_ft.numCompatibleBrands*4, 1 );
if ( box_ft.compatibleBrands == NULL ) return -1;
memcpy( box_ft.compatibleBrands, "jvt ", 4 );
return 0;
}
/*!
************************************************************************
* \brief
* The function to write the File Type Box to output file
* \return
* how many bytes been written, if success
* -1, if failed
* \param fp
* output file pointer
************************************************************************
*/
size_t wrFileTypeBox(FILE* fp)
{
size_t num = 0, ret;
assert( fp != NULL );
// to write the structure to file
num += writefile( &box_ft.type.size, 4, 1, fp );
num += writefile( &box_ft.type.type, 4, 1, fp );
num += writefile( box_ft.majorBrand, 4, 1, fp );
num += writefile( &box_ft.jmMajorVersion, 2, 1, fp );
num += writefile( &box_ft.jmMinorVersion, 2, 1, fp );
ret = fwrite( box_ft.compatibleBrands, 4, box_ft.numCompatibleBrands, fp );
num += (ret * 4);
if ( num == box_ft.type.size ) return num;
return -1;
}
/*!
************************************************************************
* \brief
* Free the memory allocated for File Type Box
* \return
* None
************************************************************************
*/
void freeFileTypeBox()
{
free( box_ft.compatibleBrands );
}
/*!
************************************************************************
* \brief
* Initiate the File Header Box
* \return
* 0, if success
* -1, otherwise
************************************************************************
*/
int initFileHeaderBox( )
{
// to write the file header
box_fh.type.size = SIZEOF_BOXTYPE + 27;
box_fh.type.type = BOX_JVTH;
box_fh.majorVersion = INTERIM_FILE_MAJOR_NO;
box_fh.minorVersion = INTERIM_FILE_MINOR_NO;
box_fh.timescale = 30000;
box_fh.numUnitsInTick = 1001;
box_fh.duration = 0; // to be updated at the end of coding
box_fh.pixAspectRatioX = 1;
box_fh.pixAspectRatioY = 1;
box_fh.maxPicId = input->PicIdModulus - 1;
box_fh.numAlternateTracks = 1;
box_fh.numBytesInPayloadCountMinusOne = 1;
box_fh.numBytesInPictureOffsetMinusTwo = 1;
box_fh.numBytesInPictureDisplayTimeMinusOne = 1;
box_fh.numBytesInPictureCountMinusOne = 1;
box_fh.numBytesInPayloadSizeMinusOne = 1;
return 0;
}
/*!
************************************************************************
* \brief
* The function to write the File Header Box to output file
* \return
* how many bytes been written, if success
* -1, if failed
* \param fp
* output file pointer
************************************************************************
*/
size_t wrFileHeaderBox( FILE* fp )
{
byte cd;
size_t num = 0;
assert( fp != NULL );
box_fh.duration = box_ati.info[0].last_frame + 1; // update
num += writefile( &box_fh.type.size, 4, 1, fp );
num += writefile( &box_fh.type.type, 4, 1, fp );
num += writefile( &box_fh.majorVersion, 1, 1, fp );
num += writefile( &box_fh.minorVersion, 1, 1, fp );
num += writefile( &box_fh.timescale, 4, 1, fp );
num += writefile( &box_fh.numUnitsInTick, 4, 1, fp );
num += writefile( &box_fh.duration, 8, 1, fp );
num += writefile( &box_fh.pixAspectRatioX, 2, 1, fp );
num += writefile( &box_fh.pixAspectRatioY, 2, 1, fp );
num += writefile( &box_fh.maxPicId, 2, 1, fp );
num += writefile( &box_fh.numAlternateTracks, 1, 1, fp );
cd = 0;
cd = (box_fh.numBytesInPayloadCountMinusOne << 6) |
(box_fh.numBytesInPictureOffsetMinusTwo << 4) |
(box_fh.numBytesInPictureDisplayTimeMinusOne << 2) |
(box_fh.numBytesInPictureCountMinusOne << 0);
num += writefile( &cd, 1, 1, fp );
cd = 0 +
(box_fh.numBytesInPayloadSizeMinusOne << 6);
num += writefile( &cd, 1, 1, fp );
if ( num == box_fh.type.size ) return num;
return -1;
}
/*!
************************************************************************
* \brief
* Free the memory allocated for File Type Box
* Do nothing
* \return
* None
************************************************************************
*/
void freeFileHeaderBox()
{
}
/*!
************************************************************************
* \brief
* Initiate the Content Info Box
* Tian Dong, Feb 10, 2002:
* Do nothing, The Box is skipped in current implementation.
* \return
* 0, if success
* -1, otherwise
************************************************************************
*/
int initContentInfoBox()
{
return 0;
}
/*!
************************************************************************
* \brief
* The function to write the Content Info Box to output file
* \return
* how many bytes been written, if success
* -1, if failed
* \param fp
* output file pointer
************************************************************************
*/
size_t wrContentInfoBox( FILE* fp )
{
return 0;
}
/*!
************************************************************************
* \brief
* Do nothing
* \return
* None
************************************************************************
*/
void freeContentInfoBox()
{
}
// Functions on AlternateTrackInfoBox
/*!
************************************************************************
* \brief
* Initiate the Alternate Track Info Box
* Tian Dong, Feb 10, 2002:
* Only one track media contained in the output file
* \return
* 0, if success
* -1, otherwise
************************************************************************
*/
int initAlternateTrackInfoBox()
{
assert(box_fh.numAlternateTracks == 1); // Only one track media contained in the output file
box_ati.type.size = SIZEOF_BOXTYPE + 12 * box_fh.numAlternateTracks;
box_ati.type.type = BOX_ATIN;
box_ati.info = calloc( sizeof(AlternateTrackInfo), box_fh.numAlternateTracks );
if ( box_ati.info == NULL ) return -1;
box_ati.info[0].displayWindowWidth = input->img_width;
box_ati.info[0].displayWindowHeight = input->img_height;
box_ati.info[0].maxSDUSize = 0; // to be updated
box_ati.info[0].avgSDUSize = 0; // to be updated
box_ati.info[0].avgBitRate = 0; // to be updated
box_ati.info[0].numSDU = 0;
box_ati.info[0].sumSDUSize = 0;
box_ati.info[0].last_frame = 0;
return 0;
}
/*!
************************************************************************
* \brief
* The function to write the Alternate Track Info Box to output file
* \return
* how many bytes been written, if success
* -1, if failed
* \param fp
* output file pointer
************************************************************************
*/
size_t wrAlternateTrackInfoBox( FILE* fp )
{
float t;
size_t num = 0;
assert( fp != NULL );
// update avgSDUSize
if ( box_ati.info[0].numSDU != 0 )
box_ati.info[0].avgSDUSize = (unsigned INT16)(box_ati.info[0].sumSDUSize / box_ati.info[0].numSDU);
t = (float)(box_ati.info[0].last_frame + 1) * (float)box_fh.numUnitsInTick / (float)box_fh.timescale;
box_ati.info[0].avgBitRate = (INT32) (box_ati.info[0].sumSDUSize / t );
// write them to the file
num += writefile( &box_ati.type.size, 4, 1, fp );
num += writefile( &box_ati.type.type, 4, 1, fp );
num += writefile( &box_ati.info[0].displayWindowWidth, 2, 1, fp );
num += writefile( &box_ati.info[0].displayWindowHeight, 2, 1, fp );
num += writefile( &box_ati.info[0].maxSDUSize, 2, 1, fp );
num += writefile( &box_ati.info[0].avgSDUSize, 2, 1, fp );
num += writefile( &box_ati.info[0].avgBitRate, 4, 1, fp );
if ( num == box_ati.type.size ) return num;
return -1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -