Skip to content

Commit 86e6d5e

Browse files
committed
Output: gop based segments
1 parent 5309627 commit 86e6d5e

File tree

4 files changed

+215
-0
lines changed

4 files changed

+215
-0
lines changed

source/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,7 @@ if(ENABLE_CLI)
717717
endif()
718718
file(GLOB OutputFiles output/output.cpp output/reconplay.cpp output/*.h
719719
output/yuv.cpp output/y4m.cpp # recon
720+
output/gop.cpp
720721
output/mp4.cpp
721722
output/mkv.cpp output/matroska_ebml.cpp
722723
output/raw.cpp) # muxers

source/output/gop.cpp

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
#include "gop.h"
2+
3+
#define NALU_LENGTH_SIZE 4
4+
5+
/*******************/
6+
7+
#define GOP_LOG_ERROR( ... ) general_log( NULL, "gop", X265_LOG_ERROR, __VA_ARGS__ )
8+
9+
#define GOP_FAIL_IF_ERR_R( cond, ... )\
10+
if( cond )\
11+
{\
12+
GOP_LOG_ERROR( __VA_ARGS__ );\
13+
b_fail = true;\
14+
clean_up();\
15+
return;\
16+
}
17+
18+
#define GOP_FAIL_IF_ERR( cond, ... )\
19+
if( cond )\
20+
{\
21+
GOP_LOG_ERROR( __VA_ARGS__ );\
22+
b_fail = true;\
23+
clean_up();\
24+
return -1;\
25+
}
26+
27+
/*******************/
28+
29+
using namespace std;
30+
31+
namespace x265 {
32+
33+
void GOPOutput::clean_up()
34+
{
35+
if(data_file) fclose(data_file);
36+
if(gop_file) fclose(gop_file);
37+
}
38+
39+
int GOPOutput::openFile(const char *gop_filename)
40+
{
41+
gop_file = fopen(gop_filename, "wb");
42+
GOP_FAIL_IF_ERR(!gop_file, "cannot open output file `%s'.\n", gop_filename);
43+
44+
const char* slash = strrchr(gop_filename, '/');
45+
if(slash == NULL) slash = strrchr(gop_filename, '\\');
46+
if(slash == NULL) {
47+
dir_prefix = "";
48+
slash = gop_filename;
49+
}
50+
else {
51+
int dir_len = slash - gop_filename + 2;
52+
char* tmp_dir_prefix = new char[dir_len];
53+
strncpy(tmp_dir_prefix, gop_filename, dir_len - 1);
54+
tmp_dir_prefix[dir_len - 1] = 0;
55+
dir_prefix = tmp_dir_prefix;
56+
slash++;
57+
}
58+
int len = strlen(slash) - 3;
59+
filename_prefix = new char[len];
60+
strncpy(filename_prefix, slash, len - 1);
61+
filename_prefix[len - 1] = 0;
62+
63+
return 0;
64+
}
65+
66+
void GOPOutput::setParam(x265_param *p_param)
67+
{
68+
p_param->bAnnexB = false;
69+
p_param->bRepeatHeaders = false;
70+
i_numframe = 0;
71+
72+
int len = strlen(dir_prefix) + strlen(filename_prefix) + 20;
73+
char opt_filename[len];
74+
sprintf(opt_filename, "%s%s.options", dir_prefix, filename_prefix);
75+
FILE* opt_file = fopen(opt_filename, "wb");
76+
GOP_FAIL_IF_ERR_R(!opt_file, "cannot open options file `%s'.\n", opt_filename);
77+
78+
fprintf(gop_file, "#options %s.options\n", filename_prefix);
79+
80+
fprintf(opt_file, "b-frames %d\n", p_param->bframes);
81+
fprintf(opt_file, "b-pyramid %d\n", p_param->bBPyramid);
82+
fprintf(opt_file, "input-timebase-num %d\n", info.timebaseNum);
83+
fprintf(opt_file, "input-timebase-den %d\n", info.timebaseDenom);
84+
fprintf(opt_file, "output-fps-num %u\n", p_param->fpsNum);
85+
fprintf(opt_file, "output-fps-den %u\n", p_param->fpsDenom);
86+
fprintf(opt_file, "source-width %d\n", p_param->sourceWidth);
87+
fprintf(opt_file, "source-height %d\n", p_param->sourceHeight);
88+
fprintf(opt_file, "sar-width %d\n", p_param->vui.sarWidth);
89+
fprintf(opt_file, "sar-height %d\n", p_param->vui.sarHeight);
90+
fprintf(opt_file, "primaries-index %d\n", p_param->vui.colorPrimaries);
91+
fprintf(opt_file, "transfer-index %d\n", p_param->vui.transferCharacteristics);
92+
fprintf(opt_file, "matrix-index %d\n", p_param->vui.matrixCoeffs >= 0 ? p_param->vui.matrixCoeffs : ISOM_MATRIX_INDEX_UNSPECIFIED);
93+
fprintf(opt_file, "full-range %d\n", p_param->vui.bEnableVideoFullRangeFlag >= 0 ? p_param->vui.bEnableVideoFullRangeFlag : 0);
94+
95+
fclose(opt_file);
96+
}
97+
98+
int GOPOutput::writeHeaders(const x265_nal* p_nal, uint32_t nalcount)
99+
{
100+
GOP_FAIL_IF_ERR(nalcount < 3, "header should contain 3+ nals");
101+
102+
int len = strlen(filename_prefix) + 20;
103+
char hdr_filename[len];
104+
sprintf(hdr_filename, "%s%s.headers", dir_prefix, filename_prefix);
105+
FILE* hdr_file = fopen(hdr_filename, "wb");
106+
GOP_FAIL_IF_ERR(!hdr_file, "cannot open headers file `%s'.\n", hdr_filename);
107+
108+
fprintf(gop_file, "#headers %s.headers\n", filename_prefix);
109+
110+
for(unsigned int i = 0; i < nalcount; i++)
111+
fwrite(p_nal[i].payload, sizeof(uint8_t), p_nal[i].sizeBytes, hdr_file);
112+
113+
fclose(hdr_file);
114+
return p_nal[0].sizeBytes + p_nal[1].sizeBytes + p_nal[2].sizeBytes;
115+
}
116+
117+
int GOPOutput::writeFrame(const x265_nal* p_nalu, uint32_t nalcount, x265_picture& pic)
118+
{
119+
const bool b_keyframe = pic.sliceType == X265_TYPE_IDR;
120+
int i_size = 0;
121+
122+
if (b_keyframe) {
123+
if (data_file)
124+
fclose(data_file);
125+
int len = strlen(filename_prefix) + 20;
126+
char data_filename[len];
127+
sprintf(data_filename, "%s%s.data-%d", dir_prefix, filename_prefix, i_numframe);
128+
data_file = fopen(data_filename, "wb");
129+
GOP_FAIL_IF_ERR(!data_file, "cannot open data file `%s'.\n", data_filename);
130+
fprintf(gop_file, "%s.data-%d\n", filename_prefix, i_numframe);
131+
fflush(gop_file);
132+
}
133+
int8_t ts_len = 2 * sizeof(int64_t);
134+
int8_t ts_lenx[4] = {0, 0, 0, ts_len};
135+
fwrite(&ts_lenx, sizeof(int8_t), 4, data_file);
136+
fwrite(&pic.pts, sizeof(int64_t), 1, data_file);
137+
fwrite(&pic.dts, sizeof(int64_t), 1, data_file);
138+
139+
for(uint8_t i = 0; i < nalcount; i++)
140+
i_size += p_nalu[i].sizeBytes;
141+
142+
for(uint8_t i = 0; i < nalcount; i++)
143+
fwrite(p_nalu[i].payload, sizeof(uint8_t), p_nalu[i].sizeBytes, data_file);
144+
145+
i_numframe++;
146+
147+
return i_size;
148+
}
149+
150+
void GOPOutput::closeFile(int64_t, int64_t)
151+
{
152+
clean_up();
153+
}
154+
155+
}

source/output/gop.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#ifndef X265_HEVC_GOP_H
2+
#define X265_HEVC_GOP_H
3+
4+
#include "output.h"
5+
#include "common.h"
6+
#include <fstream>
7+
#include <iostream>
8+
#include <lsmash.h>
9+
10+
namespace x265 {
11+
class GOPOutput : public OutputFile
12+
{
13+
protected:
14+
bool b_fail;
15+
int openFile(const char *fname);
16+
void clean_up();
17+
18+
FILE* gop_file;
19+
FILE* data_file;
20+
char* filename_prefix;
21+
const char* dir_prefix;
22+
void FixTimeScale(uint64_t &);
23+
int64_t GetTimeScaled(int64_t);
24+
InputFileInfo info;
25+
int i_numframe;
26+
27+
public:
28+
GOPOutput(const char *fname, InputFileInfo& inputInfo)
29+
{
30+
info = inputInfo;
31+
b_fail = false;
32+
gop_file = NULL;
33+
data_file = NULL;
34+
if(openFile(fname) != 0)
35+
b_fail = true;
36+
}
37+
bool isFail() const
38+
{
39+
return b_fail;
40+
}
41+
42+
bool needPTS() const { return true; }
43+
44+
const char *getName() const { return "gop"; }
45+
void setParam(x265_param *param);
46+
int writeHeaders(const x265_nal* nal, uint32_t nalcount);
47+
int writeFrame(const x265_nal* nal, uint32_t nalcount, x265_picture& pic);
48+
void closeFile(int64_t largest_pts, int64_t second_largest_pts);
49+
void release()
50+
{
51+
delete this;
52+
}
53+
};
54+
}
55+
56+
#endif

source/output/output.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "output.h"
2626
#include "yuv.h"
2727
#include "y4m.h"
28+
#include "gop.h"
2829

2930
#include "raw.h"
3031

@@ -58,6 +59,8 @@ OutputFile* OutputFile::open(const char *fname, InputFileInfo& inputInfo)
5859
if (s && !strcmp(s, ".mkv"))
5960
return new MKVOutput(fname, inputInfo);
6061
#endif
62+
if (s && !strcmp(s, ".gop"))
63+
return new GOPOutput(fname, inputInfo);
6164

6265
return new RAWOutput(fname, inputInfo);
6366
}

0 commit comments

Comments
 (0)