📄 sei.c
字号:
/*!
************************************************************************
* \file
* sei.c
* \brief
* implementation of SEI related functions
* \author(s)
* - Dong Tian <tian@cs.tut.fi>
*
************************************************************************
*/
#include <stdlib.h>
#include <assert.h>
#include <memory.h>
#include "global.h"
#include "memalloc.h"
#include "rtp.h"
#include "mbuffer.h"
#include "sei.h"
#include "vlc.h"
Boolean seiHasTemporal_reference=FALSE;
Boolean seiHasClock_timestamp=FALSE;
Boolean seiHasPanscan_rect=FALSE;
Boolean seiHasBuffering_period=FALSE;
Boolean seiHasHrd_picture=FALSE;
Boolean seiHasFiller_payload=FALSE;
Boolean seiHasUser_data_registered_itu_t_t35=FALSE;
Boolean seiHasUser_data_unregistered=FALSE;
Boolean seiHasRandom_access_point=FALSE;
Boolean seiHasRef_pic_buffer_management_repetition=FALSE;
Boolean seiHasSpare_picture=FALSE;
Boolean seiHasSceneInformation=FALSE;
Boolean seiHasSubseq_information=FALSE;
Boolean seiHasSubseq_layer_characteristics=FALSE;
Boolean seiHasSubseq_characteristics=FALSE;
/*
************************************************************************
* \basic functions on supplemental enhancement information
* \brief
* The implementations are based on FCD
************************************************************************
*/
//! sei_message[0]: this struct is to store the sei message packetized independently
//! sei_message[1]: this struct is to store the sei message packetized together with slice data
sei_struct sei_message[2];
void InitSEIMessages()
{
int i;
for (i=0; i<2; i++)
{
sei_message[i].data = malloc(MAXRTPPAYLOADLEN);
if( sei_message[i].data == NULL ) no_mem_exit("InitSEIMessages: sei_message[i].data");
sei_message[i].subPacketType = SEI_PACKET_TYPE;
clear_sei_message(i);
}
// init sei messages
seiSparePicturePayload.data = NULL;
InitSparePicture();
InitSubseqChar();
if (input->NumFramesInELSubSeq != 0)
InitSubseqLayerInfo();
InitSceneInformation(); // JVT-D099
// init panscanrect sei message
InitPanScanRectInfo();
// init user_data_unregistered
InitUser_data_unregistered();
// init user_data_unregistered
InitUser_data_registered_itu_t_t35();
// init user_RandomAccess
InitRandomAccess();
}
void CloseSEIMessages()
{
int i;
if (input->NumFramesInELSubSeq != 0)
CloseSubseqLayerInfo();
CloseSubseqChar();
CloseSparePicture();
CloseSceneInformation(); // JVT-D099
//Shankar Regunathan Oct 2002
ClosePanScanRectInfo();
CloseUser_data_unregistered();
CloseUser_data_registered_itu_t_t35();
CloseRandomAccess();
for (i=0; i<MAX_LAYER_NUMBER; i++)
{
if ( sei_message[i].data ) free( sei_message[i].data );
sei_message[i].data = NULL;
}
}
Boolean HaveAggregationSEI()
{
if (sei_message[AGGREGATION_SEI].available && img->type != B_SLICE)
return TRUE;
if (seiHasSubseqInfo)
return TRUE;
if (seiHasSubseqLayerInfo && img->number == 0)
return TRUE;
if (seiHasSubseqChar)
return TRUE;
if (seiHasSceneInformation)
return TRUE;
if (seiHasPanScanRectInfo)
return TRUE;
if (seiHasUser_data_unregistered_info)
return TRUE;
if (seiHasUser_data_registered_itu_t_t35_info)
return TRUE;
if (seiHasRecoveryPoint_info)
return TRUE;
return FALSE;
// return input->SparePictureOption && ( seiHasSpare_picture || seiHasSubseq_information ||
// seiHasSubseq_layer_characteristics || seiHasSubseq_characteristics );
}
/*!
************************************************************************
* \brief
* write one sei payload to the sei message
* \param id
* 0, if this is the normal packet\n
* 1, if this is a aggregation packet
* \param payload
* a pointer that point to the sei payload. Note that the bitstream
* should have be byte aligned already.
* \param payload_size
* the size of the sei payload
* \param payload_type
* the type of the sei payload
* \par Output
* the content of the sei message (sei_message[id]) is updated.
************************************************************************
*/
void write_sei_message(int id, byte* payload, int payload_size, int payload_type)
{
int offset, type, size;
assert(payload_type >= 0 && payload_type < SEI_MAX_ELEMENTS);
type = payload_type;
size = payload_size;
offset = sei_message[id].payloadSize;
while ( type > 255 )
{
sei_message[id].data[offset++] = 0xFF;
type = type - 255;
}
sei_message[id].data[offset++] = type;
while ( size > 255 )
{
sei_message[id].data[offset++] = 0xFF;
size = size - 255;
}
sei_message[id].data[offset++] = size;
memcpy(sei_message[id].data + offset, payload, payload_size);
offset += payload_size;
sei_message[id].payloadSize = offset;
}
/*!
************************************************************************
* \brief
* write rbsp_trailing_bits to the sei message
* \param id
* 0, if this is the normal packet \n
* 1, if this is a aggregation packet
* \par Output
* the content of the sei message is updated and ready for packetisation
************************************************************************
*/
void finalize_sei_message(int id)
{
int offset = sei_message[id].payloadSize;
sei_message[id].data[offset] = 0x80;
sei_message[id].payloadSize++;
sei_message[id].available = TRUE;
}
/*!
************************************************************************
* \brief
* empty the sei message buffer
* \param id
* 0, if this is the normal packet \n
* 1, if this is a aggregation packet
* \par Output
* the content of the sei message is cleared and ready for storing new
* messages
************************************************************************
*/
void clear_sei_message(int id)
{
memset( sei_message[id].data, 0, MAXRTPPAYLOADLEN);
sei_message[id].payloadSize = 0;
sei_message[id].available = FALSE;
}
/*!
************************************************************************
* \brief
* copy the bits from one bitstream buffer to another one
* \param dest
* pointer to the dest bitstream buffer
* \param source
* pointer to the source bitstream buffer
* \par Output
* the content of the dest bitstream is changed.
************************************************************************
*/
void AppendTmpbits2Buf( Bitstream* dest, Bitstream* source )
{
int i, j;
unsigned char mask;
int bits_in_last_byte;
// copy the first bytes in source buffer
for (i=0; i<source->byte_pos; i++)
{
mask = 0x80;
for (j=0; j<8; j++)
{
dest->byte_buf <<= 1;
if (source->streamBuffer[i] & mask)
dest->byte_buf |= 1;
dest->bits_to_go--;
mask >>= 1;
if (dest->bits_to_go==0)
{
dest->bits_to_go = 8;
dest->streamBuffer[dest->byte_pos++]=dest->byte_buf;
dest->byte_buf = 0;
}
}
}
// copy the last byte, there are still (8-source->bits_to_go) bits in the source buffer
bits_in_last_byte = 8-source->bits_to_go;
if ( bits_in_last_byte > 0 )
{
mask = 1 << (bits_in_last_byte-1);
for (j=0; j<bits_in_last_byte; j++)
{
dest->byte_buf <<= 1;
if (source->byte_buf & mask)
dest->byte_buf |= 1;
dest->bits_to_go--;
mask >>= 1;
if (dest->bits_to_go==0)
{
dest->bits_to_go = 8;
dest->streamBuffer[dest->byte_pos++]=dest->byte_buf;
dest->byte_buf = 0;
}
}
}
}
/*
**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* \functions on spare pictures
* \brief
* implementation of Spare Pictures related functions based on
* JVT-D100
* \author
* Dong Tian <tian@cs.tut.fi>
**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*/
// global variables for spare pictures
// Tian Dong (Sept 2002)
// In current implementation, Sept 2002, the spare picture info is
// paketized together with the immediately following frame. Thus we
// define one set of global variables to save the info.
Boolean seiHasSparePicture = FALSE;
spare_picture_struct seiSparePicturePayload;
/*!
************************************************************************
* \brief
* Init the global variables for spare picture information
************************************************************************
*/
void InitSparePicture()
{
if ( seiSparePicturePayload.data != NULL ) CloseSparePicture();
seiSparePicturePayload.data = malloc( sizeof(Bitstream) );
if ( seiSparePicturePayload.data == NULL ) no_mem_exit("InitSparePicture: seiSparePicturePayload.data");
seiSparePicturePayload.data->streamBuffer = malloc(MAXRTPPAYLOADLEN);
if ( seiSparePicturePayload.data->streamBuffer == NULL ) no_mem_exit("InitSparePicture: seiSparePicturePayload.data->streamBuffer");
memset( seiSparePicturePayload.data->streamBuffer, 0, MAXRTPPAYLOADLEN);
seiSparePicturePayload.num_spare_pics = 0;
seiSparePicturePayload.target_frame_num = 0;
seiSparePicturePayload.data->bits_to_go = 8;
seiSparePicturePayload.data->byte_pos = 0;
seiSparePicturePayload.data->byte_buf = 0;
}
/*!
************************************************************************
* \brief
* Close the global variables for spare picture information
************************************************************************
*/
void CloseSparePicture()
{
if (seiSparePicturePayload.data->streamBuffer)
free(seiSparePicturePayload.data->streamBuffer);
seiSparePicturePayload.data->streamBuffer = NULL;
if (seiSparePicturePayload.data)
free(seiSparePicturePayload.data);
seiSparePicturePayload.data = NULL;
seiSparePicturePayload.num_spare_pics = 0;
seiSparePicturePayload.target_frame_num = 0;
}
/*!
************************************************************************
* \brief
* Calculate the spare picture info, save the result in map_sp
* then compose the spare picture information.
* \par Output
* the spare picture payload is available in *seiSparePicturePayload*
* the syntax elements in the loop (see FCD), excluding the two elements
* at the beginning.
************************************************************************
*/
void CalculateSparePicture()
{
/*
int i, j, tmp, i0, j0, m;
byte **map_sp;
int delta_spare_frame_num;
Bitstream *tmpBitstream;
int num_of_mb=(img->height/16) * (img->width/16);
int threshold1 = 16*16*input->SPDetectionThreshold;
int threshold2 = num_of_mb * input->SPPercentageThreshold / 100;
int ref_area_indicator;
int CandidateSpareFrameNum, SpareFrameNum;
int possible_spare_pic_num;
// define it for debug purpose
#define WRITE_MAP_IMAGE
#ifdef WRITE_MAP_IMAGE
byte **y;
int k;
FILE* fp;
static int first = 1;
char map_file_name[255]="map.yuv";
#endif
// basic check
if (fb->picbuf_short[0]->used==0 || fb->picbuf_short[1]->used==0)
{
#ifdef WRITE_MAP_IMAGE
fp = fopen( map_file_name, "wb" );
assert( fp != NULL );
// write the map image
for (i=0; i < img->height; i++)
for (j=0; j < img->width; j++)
fputc(0, fp);
for (k=0; k < 2; k++)
for (i=0; i < img->height/2; i++)
for (j=0; j < img->width/2; j++)
fputc(128, fp);
fclose( fp );
#endif
seiHasSparePicture = FALSE;
return;
}
seiHasSparePicture = TRUE;
// set the global bitstream memory.
InitSparePicture();
seiSparePicturePayload.target_frame_num = img->number % MAX_FN;
// init the local bitstream memory.
tmpBitstream = malloc(sizeof(Bitstream));
if ( tmpBitstream == NULL ) no_mem_exit("CalculateSparePicture: tmpBitstream");
tmpBitstream->streamBuffer = malloc(MAXRTPPAYLOADLEN);
if ( tmpBitstream->streamBuffer == NULL ) no_mem_exit("CalculateSparePicture: tmpBitstream->streamBuffer");
memset( tmpBitstream->streamBuffer, 0, MAXRTPPAYLOADLEN);
#ifdef WRITE_MAP_IMAGE
if ( first )
{
fp = fopen( map_file_name, "wb" );
first = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -