forked from aizvorski/h264bitstream
-
Notifications
You must be signed in to change notification settings - Fork 2
/
svc_split.c
188 lines (145 loc) · 6.87 KB
/
svc_split.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
//
// svc_split.c
// h264bitstream-svc
//
// Created by qiwa on 12/18/16.
// Copyright © 2016 qiwa. All rights reserved.
//
#include <stdio.h>
#include "h264_stream.h"
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#define BUFSIZE 32*1024*1024
int main(int argc, char *argv[])
{
uint8_t* buf = (uint8_t*)malloc( BUFSIZE );
h264_stream_t* h = h264_new();
FILE* infile = fopen(argv[1], "rb");
if (infile == NULL) { fprintf( stderr, "!! Error: could not open file: %s \n", strerror(errno)); exit(EXIT_FAILURE); }
char fname_buf[1024] = {0};
//create base layer file
sprintf(fname_buf, "%s.base", argv[1]);
FILE* outfile_base = fopen(fname_buf, "wb");
if (outfile_base == NULL) { fprintf( stderr, "!! Error: could not open file: %s \n", strerror(errno)); exit(EXIT_FAILURE); }
//scalable layer
FILE* outfile_layers[32] = {0};
//misc packets file
memset(fname_buf, 0, 1024);
sprintf(fname_buf, "%s.misc", argv[1]);
FILE* outfile_misc = fopen(fname_buf, "wb");
if (outfile_misc == NULL) { fprintf( stderr, "!! Error: could not open file: %s \n", strerror(errno)); exit(EXIT_FAILURE); }
if (h264_dbgfile == NULL) { h264_dbgfile = stdout; }
size_t rsz = 0;
size_t sz = 0;
int64_t off = 0;
uint8_t* p = buf;
int nal_start, nal_end;
//this is to identify whether pps is written or not
char *pps_buf[32];
int pps_buf_size[32];
while (1)
{
rsz = fread(buf + sz, 1, BUFSIZE - sz, infile);
if (rsz == 0)
{
if (ferror(infile)) { fprintf( stderr, "!! Error: read failed: %s \n", strerror(errno)); break; }
break; // if (feof(infile))
}
sz += rsz;
while (find_nal_unit(p, sz, &nal_start, &nal_end) > 0)
{
fprintf( h264_dbgfile, "!! Found NAL at offset %lld (0x%04llX), size %lld (0x%04llX) \n",
(long long int)(off + (p - buf) + nal_start),
(long long int)(off + (p - buf) + nal_start),
(long long int)(nal_end - nal_start),
(long long int)(nal_end - nal_start) );
fprintf( h264_dbgfile, "XX ");
debug_bytes(p, nal_end - nal_start >= 16 ? 16: nal_end - nal_start);
p += nal_start;
read_debug_nal_unit(h, p, nal_end - nal_start);
//check nal type
switch (h->nal->nal_unit_type)
{
case NAL_UNIT_TYPE_CODED_SLICE_IDR:
case NAL_UNIT_TYPE_CODED_SLICE_NON_IDR:
case NAL_UNIT_TYPE_CODED_SLICE_AUX:
printf("reference pps: %d & sps: %d\n", h->sh->pic_parameter_set_id,
h->pps_table[h->sh->pic_parameter_set_id]->seq_parameter_set_id);
if (pps_buf[h->sh->pic_parameter_set_id] != NULL)
{
fwrite(pps_buf[h->sh->pic_parameter_set_id], 1, pps_buf_size[h->sh->pic_parameter_set_id], outfile_base);
free(pps_buf[h->sh->pic_parameter_set_id]);
pps_buf[h->sh->pic_parameter_set_id] = NULL;
}
//start saving the slices
fwrite(p - nal_start, 1, nal_end, outfile_base);
break;
case NAL_UNIT_TYPE_SPS:
fwrite(p - nal_start, 1, nal_end, outfile_base);
break;
case NAL_UNIT_TYPE_PPS:
pps_buf[h->pps->pic_parameter_set_id] = malloc(nal_end);
memcpy(pps_buf[h->pps->pic_parameter_set_id], p - nal_start, nal_end);
pps_buf_size[h->pps->pic_parameter_set_id] = nal_end;
break;
//SVC support
case NAL_UNIT_TYPE_SUBSET_SPS:
printf("sps_ext id: %d\n", h->sps_subset->sps->seq_parameter_set_id);
memset(fname_buf, 0, 1024);
sprintf(fname_buf, "%s.l_%d", argv[1], h->sps_subset->sps->seq_parameter_set_id);
outfile_layers[h->sps_subset->sps->seq_parameter_set_id] = fopen(fname_buf, "wb");
if (outfile_layers[h->sps_subset->sps->seq_parameter_set_id] == NULL) { fprintf( stderr, "!! Error: could not open file: %s \n", strerror(errno)); exit(EXIT_FAILURE); }
fwrite(p - nal_start, 1, nal_end, outfile_layers[h->sps_subset->sps->seq_parameter_set_id]);
break;
//SVC support
case NAL_UNIT_TYPE_CODED_SLICE_SVC_EXTENSION:
printf("reference extension pps: %d & sps: %d\n", h->sh->pic_parameter_set_id,
h->pps_table[h->sh->pic_parameter_set_id]->seq_parameter_set_id);
if (pps_buf[h->sh->pic_parameter_set_id] != NULL)
{
fwrite(pps_buf[h->sh->pic_parameter_set_id], 1, pps_buf_size[h->sh->pic_parameter_set_id], outfile_layers[h->pps_table[h->sh->pic_parameter_set_id]->seq_parameter_set_id]);
free(pps_buf[h->sh->pic_parameter_set_id]);
pps_buf[h->sh->pic_parameter_set_id] = NULL;
}
//start saving the slices
fwrite(p - nal_start, 1, nal_end, outfile_layers[h->pps_table[h->sh->pic_parameter_set_id]->seq_parameter_set_id]);
break;
default:
fwrite(p - nal_start, 1, nal_end, outfile_misc);
break;
}
//save nal to corresponding file
//skip to next NAL
p += (nal_end - nal_start);
sz -= nal_end;
}
// if no NALs found in buffer, discard it
if (p == buf)
{
fprintf( stderr, "!! Did not find any NALs between offset %lld (0x%04llX), size %lld (0x%04llX), discarding \n",
(long long int)off,
(long long int)off,
(long long int)off + sz,
(long long int)off + sz);
p = buf + sz;
sz = 0;
}
memmove(buf, p, sz);
off += p - buf;
p = buf;
}
h264_free(h);
free(buf);
fclose(h264_dbgfile);
fclose(infile);
fclose(outfile_base);
fclose(outfile_misc);
for(int i = 0; i < 32; i++) {
if (outfile_layers[i] != NULL)
fclose(outfile_layers[i]);
}
return 0;
}