📄 header.c
字号:
// *************************************************************************************
// *************************************************************************************
// header.c H.26L Slice, Picture, and Sequence headers
//
// Main contributors (see contributors.h for copyright, address and affiliation details)
//
// Stephan Wenger <stewe@cs.tu-berlin.de>
// *************************************************************************************
// *************************************************************************************
#include <math.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "defines.h"
#include "global.h"
#include "header.h"
#include "elements.h"
// A little trick to avoid those horrible #if TRACE all over the source code
#if TRACE
#define SYMTRACESTRING(s) strcpy(sym.tracestring,s)
#else
#define SYMTRACESTRING(s) /* to nothing */
#endif
// Local Functions
static int PutSliceStartCode(Bitstream *s);
static int PutPictureStartCode (Bitstream *s);
static int PutStartCode (int Type, Bitstream *s, char *ts);
// static void select_picture_type (SyntaxElement *symbol);
// End local Functions
int PictureHeader() {
// StW: PictureTypeSymbol is the Symbol used to encode the picture type.
// This is one of the dirtiest hacks if have seen so far from people who
// usually know what they are doing :-)
// img->type has one of three possible values (I, P, B), the picture type as coded
// distiguishes further by nidicating whether one or more reference frames are
// used for P and B frames 9hence 5 values). See decoder/defines.h
// The mapping is performed in image.c select_picture_type()
int dP_nr = assignSE2partition[input->partition_mode][SE_HEADER];
Bitstream *currStream = ((img->currentSlice)->partArr[dP_nr]).bitstream;
DataPartition *partition = &((img->currentSlice)->partArr[dP_nr]);
SyntaxElement sym;
int len = 0;
sym.type = SE_HEADER; // This will be true for all symbols generated here
sym.mapping = n_linfo2; // Mapping rule: Simple code number to len/info
// A bit of checking, for debug purposes only, will not be in code later
assert(img->current_mb_nr == 0);
// Ok. We are sure we want to code a Picture Header. So, first: Put PSC
len+=PutPictureStartCode (currStream);
// Now, take care of te UVLC coded data structure described in VCEG-M79
sym.value1 = 0; // TRType = 0
SYMTRACESTRING("PH TemporalReferenceType");
len += writeSyntaxElement_UVLC (&sym, partition);
sym.value1 = img->tr%256; // TR, variable length
SYMTRACESTRING("PH TemporalReference");
len += writeSyntaxElement_UVLC (&sym, partition);
// Size information. If the picture is Intra, then transmit the size in MBs,
// For all other picture type just indicate that it didn't change.
// Note: this is currently the prudent way to do things, because we do not
// have anything similar to Annex P of H.263. However, we should anticipate
// taht one day we may want to have an Annex P type functionality. Hence, it is
// unwise to assume that P pictures will never have a size indiciation. So the
// one bit for an "unchanged" inidication is well spent.
if (img->type == INTRA_IMG) {
// Double check that width and height are divisible by 16
assert (img->width % 16 == 0);
assert (img->height % 16 == 0);
sym.value1 = 1; // SizeType = Width/Height in MBs
SYMTRACESTRING("PH FullSizeInformation");
len += writeSyntaxElement_UVLC (&sym, partition);
sym.value1 = img->width / 16;
SYMTRACESTRING("PH FullSize-X");
len += writeSyntaxElement_UVLC (&sym, partition);
sym.value1 = img->height / 16;
SYMTRACESTRING("PH FullSize-Y");
len += writeSyntaxElement_UVLC (&sym, partition);
} else { // Not an intra frame -> write "unchanged"
sym.value1 = 0; // SizeType = Unchanged
SYMTRACESTRING("PHSizeUnchanged");
len += writeSyntaxElement_UVLC (&sym, partition);
}
select_picture_type (&sym);
SYMTRACESTRING("Hacked Picture Type Symbol");
len+= writeSyntaxElement_UVLC (&sym, partition);
// Now always put TR
// Finally, write Reference Picture ID (same as TR here).
sym.value1 = img->tr%256; // TR, variable length
SYMTRACESTRING("PHRefPicID");
len += writeSyntaxElement_UVLC (&sym, partition);
return len;
}
int SliceHeader(int UseStartCode) {
int dP_nr = assignSE2partition[input->partition_mode][SE_HEADER];
Bitstream *currStream = ((img->currentSlice)->partArr[dP_nr]).bitstream;
DataPartition *partition = &((img->currentSlice)->partArr[dP_nr]);
SyntaxElement sym;
int len = 0;
int Quant = img->qp; // Hack. This should be a parameter as soon as Gisle is done
int MBPosition = img->current_mb_nr; // Hack. This should be a paremeter as well.
sym.type = SE_HEADER; // This will be true for all symbols generated here
sym.mapping = n_linfo2; // Mapping rule: Simple code number to len/info
// Note 1. Current implementation: Slice start code is similar to pictrure start code
// (info is 1 for slice and 0 for picture start code). Slice Start code is not
// present except when generating an UVLC file. Start codes are typical NAL
// functionality, and hence NALs will take care the issue in the future.
// Note 2: Traditionally, the QP is a bit mask. However, at numerically large QPs
// we usually have high compression and don't want to waste bits, whereas
// at low QPs this is not as much an issue. Hence, the QUANT parameter
// is coded as a UVLC calculated as 31 - QUANT. That is, the UVLC representation
// of 31-QUANT is coded, instead of QUANT.
// Note 3: In addition to the fields in VCEG-M79 there is one additional header field
// with the MV resolution. Currently defined values:
// 0 == 1/4th pel resolution (old default)
// 1 == 1/8th pel resolution
// ... could be enhanced straightforward, it may make sense to define
// 2 == 1/2 pel resolution
// 3 == full pel resolution
if (UseStartCode) {
// Input mode 0, File Format, and not Picture Start (first slice in picture)
// This is the only case where a slice start code makes sense
//
// Putting a Slice Start Code is the same like the picture start code. It's
// n ot as straightforward as one thinks, See remarks above.
len += PutSliceStartCode(currStream);
};
// Now we have coded the Pciture header when appropriate, and the slice header when
// appropriate. Follow with the content of the slice header: GOB address of the slice
// start and (initial) QP. For the QP see remarks above. For the GOB address, use
// straigtforward procedure. Note that this allows slices to start at MB addresses
// up to 2^15 MBs due ot start code emulation problems. This should be enough for
// most practical applications,. but probably not for cinema. Has to be discussed.
// For the MPEG tests this is irrelevant, because there the rule will be one silce--
// one picture.
// Put MB-Adresse
assert (MBPosition < (1<<15));
SYMTRACESTRING("SH FirstMBInSlice");
sym.value1 = MBPosition;
len += writeSyntaxElement_UVLC (&sym, partition);
// Put Quant. It's a bit irrationale that we still put the same quant here, but it's
// a good provision for the future. In real-world applications slices typically
// start with Intra information, and Intra MBs will likely use a different quant
// than Inter
SYMTRACESTRING("SH SliceQuant");
sym.value1 = 31 - Quant;
len += writeSyntaxElement_UVLC (&sym, partition);
// printf ("Wrote SliceQuant len %d info %d, value %d\n", sym.len, sym.inf, sym.value1);
// Put the Motion Vector resolution as per reflector consensus
SYMTRACESTRING("SH MVResolution");
sym.value1 = input->mv_res;
len += writeSyntaxElement_UVLC (&sym, partition);
// printf ("Write MVResolution len %d info %d, value %d\n", sym.len, sym.inf, sym.value1);
return len;
}
int SequenceHeader (FILE *outf) {
//int LenInBytes = 0;
int HeaderInfo; // Binary coded Headerinfo to be written in file
int ProfileLevelVersionHash;
switch (input->SequenceHeaderType) {
case 0:
// No SequenceHeader, do nothing
return 0;
case 1:
// A binary mini Sequence header. Fixed length 32 bits. Defined as follows
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | 0 | 1 | 2 | 3 |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | TR Modulus | PicIDModulus |OfMode |part |S|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
// S is symbol_mode (UVLC = 0, CABAC = 1), the other are as in the input file
assert (input->TRModulus < 4096);
assert (sizeof (int) == 4);
assert (input->PicIdModulus <4096);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -