Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

h.264 "fixer" tool #95

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/bitstream.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ namespace Utils{
return i;
}

size_t getOffset(){return offset;}

private:
bool checkBufferSize(unsigned int size);
long long unsigned int golombGetter();
Expand Down
63 changes: 61 additions & 2 deletions lib/h264.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <cmath>
#include <cstring>
#include <iomanip>
#include <sstream>

namespace h264{

Expand Down Expand Up @@ -479,7 +480,13 @@ namespace h264{
log2MaxPicOrderCntLsbMinus4 = bs.getUExpGolomb();
derived_maxPicOrderCntLsb = pow(2, log2MaxPicOrderCntLsbMinus4 + 4);
}else if (picOrderCntType == 1){
WARN_MSG("picOrderCntType == 1 encountered, which has not-yet implemented parameters");
deltaPicOrderAlwaysZeroFlag = bs.get(1);
bs.getExpGolomb(); // offset_for_non_ref_pic
bs.getExpGolomb(); // offset_for_top_to_bottom_field
numRefFramesInPicOrderCntCycle = bs.getUExpGolomb();
for (size_t i = 0; i < numRefFramesInPicOrderCntCycle; i++){
bs.getExpGolomb(); // offset_for_ref_frame[i]
}
return;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am an idiot - this "return" should get removed. Obviously, it was there with the WARN_MSG. I accidentally removed this file during formatting and had to recreate changes from older backup. Forgot about this one :-(

}
maxNumRefFrames = bs.getUExpGolomb();
Expand Down Expand Up @@ -974,7 +981,11 @@ namespace h264{

codedSliceUnit::codedSliceUnit(const char *data, size_t len) : nalUnit(data, len){
Utils::bitstream bs;
for (size_t i = 1; i < len; i++){
// We only want to parse a part of the header here. From standard it seems
// that maximum possible lenght will be less than 100 bits, so using 16
// bytes for safety
size_t l = len < 16 ? len : 16;
for (size_t i = 1; i < l; i++){
if (i + 2 < len && (memcmp(data + i, "\000\000\003", 3) == 0)){// Emulation prevention bytes
// Yes, we increase i here
bs.append(data + i, 2);
Expand All @@ -989,6 +1000,54 @@ namespace h264{
picParameterSetId = bs.getUExpGolomb();
}

codedSliceUnit::codedSliceUnit(const char *data, size_t len, const spsUnit &sps, const ppsUnit &pps)
: nalUnit(data, len){
Utils::bitstream bs;
// We only want to parse slice header here. Maximum possible length seems
// to be around 50 bytes, so using 64 bytes for safety
size_t l = len < 64 ? len : 64;
for (size_t i = 1; i < l; i++){
if (i + 2 < l && (memcmp(data + i, "\000\000\003", 3) == 0)){// Emulation prevention bytes
// Yes, we increase i here
bs.append(data + i, 2);
i += 2;
}else{
// No we don't increase i here
bs.append(data + i, 1);
}
}
firstMbInSlice = bs.getUExpGolomb();
sliceType = bs.getUExpGolomb();
picParameterSetId = bs.getUExpGolomb();

frameNum = bs.get(sps.log2MaxFrameNumMinus4 + 4);
if (!sps.frameMbsOnlyFlag){
fieldPicFlag = bs.get(1);
if (fieldPicFlag){bottomFieldFlag = bs.get(1);}
}

// IDR frames have idrPicId here
if (5 == getType()){idrPicId = bs.getUExpGolomb();}

picOrderCntLsb = deltaPicOrderCntBottom = 0;
if (0 == sps.picOrderCntType){
picOrderCntLsb = bs.get(sps.log2MaxPicOrderCntLsbMinus4 + 4);
if (pps.bottomFieldPicOrderInFramePresentFlag && !fieldPicFlag){
deltaPicOrderCntBottom = bs.getExpGolomb();
}
}

deltaPicOrderCnt[0] = deltaPicOrderCnt[1] = 0;
if ((1 == sps.picOrderCntType) && !sps.deltaPicOrderAlwaysZeroFlag){
deltaPicOrderCnt[0] = bs.getExpGolomb();
if (pps.bottomFieldPicOrderInFramePresentFlag && fieldPicFlag){
deltaPicOrderCnt[1] = bs.getExpGolomb();
}
}

if (pps.redundantPicCntPresentFlag){redundantPicCnt = bs.getUExpGolomb();}
}

void codedSliceUnit::setPPSNumber(size_t newNumber){
// for now, can only convert from 0 to 16
if (picParameterSetId != 0){return;}
Expand Down
23 changes: 20 additions & 3 deletions lib/h264.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <cstdio>
#include <cstdlib>
#include <deque>
#include <iostream>
#include <string>

#include "bitfields.h"
Expand Down Expand Up @@ -81,8 +82,9 @@ namespace h264{
nalUnit(const char *data, size_t len) : payload(data, len){}
virtual ~nalUnit(){}

uint8_t getType(){return payload[0] & 0x1F;}
size_t getSize(){return payload.size();}
uint8_t getType() const{ return payload[0] & 0x1F;}
uint8_t getRefNalIdc() const{ return payload[0] >> 5;}
size_t getSize() const{ return payload.size();}
virtual void toPrettyString(std::ostream &out){
out << "Nal unit of type " << (((uint8_t)payload[0]) & 0x1F) << ", " << payload.size()
<< " bytes long" << std::endl;
Expand Down Expand Up @@ -195,7 +197,8 @@ namespace h264{
uint64_t picOrderCntType;
uint64_t log2MaxPicOrderCntLsbMinus4;

// Here go values for pic_order_cnt_type == 1
bool deltaPicOrderAlwaysZeroFlag;
uint64_t numRefFramesInPicOrderCntCycle;

uint64_t maxNumRefFrames;
bool gapsInFrameNumValueAllowedFlag;
Expand Down Expand Up @@ -284,13 +287,27 @@ namespace h264{
};
class codedSliceUnit : public nalUnit{
public:
// "partial" constructor just to get picParameterSetId, as full parsing
// is not possible without PPS/SPS pair
codedSliceUnit(const char *data, size_t len);
// "full" constructor when PPS/SPS pair is supplied
codedSliceUnit(const char *data, size_t len, const spsUnit &sps, const ppsUnit &pps);
void setPPSNumber(size_t newNumber);
void toPrettyString(std::ostream &out);

uint64_t firstMbInSlice;
uint64_t sliceType;
uint64_t picParameterSetId;

uint64_t frameNum;
bool fieldPicFlag;
bool bottomFieldFlag;
uint64_t idrPicId;
uint64_t picOrderCntType;
uint64_t picOrderCntLsb;
uint64_t deltaPicOrderCntBottom;
uint64_t deltaPicOrderCnt[2];
uint64_t redundantPicCnt;
};

class seiUnit : public nalUnit{
Expand Down
Loading