1 /*****************************************************************************
2 * flv.c: flv muxer
3 *****************************************************************************
4 * Copyright (C) 2009-2021 x264 project
5 *
6 * Authors: Kieran Kunhya <kieran@kunhya.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
21 *
22 * This program is also available under a commercial proprietary license.
23 * For more information, contact us at licensing@x264.com.
24 *****************************************************************************/
25
26 #include "output.h"
27 #include "flv_bytestream.h"
28
29 #define CHECK(x)\
30 do {\
31 if( (x) < 0 )\
32 return -1;\
33 } while( 0 )
34
35 typedef struct
36 {
37 flv_buffer *c;
38
39 uint8_t *sei;
40 int sei_len;
41
42 int64_t i_fps_num;
43 int64_t i_fps_den;
44 int64_t i_framenum;
45
46 uint64_t i_framerate_pos;
47 uint64_t i_duration_pos;
48 uint64_t i_filesize_pos;
49 uint64_t i_bitrate_pos;
50
51 uint8_t b_write_length;
52 int64_t i_prev_dts;
53 int64_t i_prev_cts;
54 int64_t i_delay_time;
55 int64_t i_init_delta;
56 int i_delay_frames;
57
58 double d_timebase;
59 int b_vfr_input;
60 int b_dts_compress;
61
62 unsigned start;
63 } flv_hnd_t;
64
write_header(flv_buffer * c)65 static int write_header( flv_buffer *c )
66 {
67 flv_put_tag( c, "FLV" ); // Signature
68 flv_put_byte( c, 1 ); // Version
69 flv_put_byte( c, 1 ); // Video Only
70 flv_put_be32( c, 9 ); // DataOffset
71 flv_put_be32( c, 0 ); // PreviousTagSize0
72
73 return flv_flush_data( c );
74 }
75
open_file(char * psz_filename,hnd_t * p_handle,cli_output_opt_t * opt)76 static int open_file( char *psz_filename, hnd_t *p_handle, cli_output_opt_t *opt )
77 {
78 flv_hnd_t *p_flv = calloc( 1, sizeof(flv_hnd_t) );
79 if( p_flv )
80 {
81 flv_buffer *c = flv_create_writer( psz_filename );
82 if( c )
83 {
84 if( !write_header( c ) )
85 {
86 p_flv->c = c;
87 p_flv->b_dts_compress = opt->use_dts_compress;
88 *p_handle = p_flv;
89 return 0;
90 }
91
92 fclose( c->fp );
93 free( c->data );
94 free( c );
95 }
96 free( p_flv );
97 }
98
99 *p_handle = NULL;
100 return -1;
101 }
102
set_param(hnd_t handle,x264_param_t * p_param)103 static int set_param( hnd_t handle, x264_param_t *p_param )
104 {
105 flv_hnd_t *p_flv = handle;
106 flv_buffer *c = p_flv->c;
107
108 flv_put_byte( c, FLV_TAG_TYPE_META ); // Tag Type "script data"
109
110 int start = c->d_cur;
111 flv_put_be24( c, 0 ); // data length
112 flv_put_be24( c, 0 ); // timestamp
113 flv_put_be32( c, 0 ); // reserved
114
115 flv_put_byte( c, AMF_DATA_TYPE_STRING );
116 flv_put_amf_string( c, "onMetaData" );
117
118 flv_put_byte( c, AMF_DATA_TYPE_MIXEDARRAY );
119 flv_put_be32( c, 7 );
120
121 flv_put_amf_string( c, "width" );
122 flv_put_amf_double( c, p_param->i_width );
123
124 flv_put_amf_string( c, "height" );
125 flv_put_amf_double( c, p_param->i_height );
126
127 flv_put_amf_string( c, "framerate" );
128
129 if( !p_param->b_vfr_input )
130 flv_put_amf_double( c, (double)p_param->i_fps_num / p_param->i_fps_den );
131 else
132 {
133 p_flv->i_framerate_pos = c->d_cur + c->d_total + 1;
134 flv_put_amf_double( c, 0 ); // written at end of encoding
135 }
136
137 flv_put_amf_string( c, "videocodecid" );
138 flv_put_amf_double( c, FLV_CODECID_H264 );
139
140 flv_put_amf_string( c, "duration" );
141 p_flv->i_duration_pos = c->d_cur + c->d_total + 1;
142 flv_put_amf_double( c, 0 ); // written at end of encoding
143
144 flv_put_amf_string( c, "filesize" );
145 p_flv->i_filesize_pos = c->d_cur + c->d_total + 1;
146 flv_put_amf_double( c, 0 ); // written at end of encoding
147
148 flv_put_amf_string( c, "videodatarate" );
149 p_flv->i_bitrate_pos = c->d_cur + c->d_total + 1;
150 flv_put_amf_double( c, 0 ); // written at end of encoding
151
152 flv_put_amf_string( c, "" );
153 flv_put_byte( c, AMF_END_OF_OBJECT );
154
155 unsigned length = c->d_cur - start;
156 flv_rewrite_amf_be24( c, length - 10, start );
157
158 flv_put_be32( c, length + 1 ); // tag length
159
160 p_flv->i_fps_num = p_param->i_fps_num;
161 p_flv->i_fps_den = p_param->i_fps_den;
162 p_flv->d_timebase = (double)p_param->i_timebase_num / p_param->i_timebase_den;
163 p_flv->b_vfr_input = p_param->b_vfr_input;
164 p_flv->i_delay_frames = p_param->i_bframe ? (p_param->i_bframe_pyramid ? 2 : 1) : 0;
165
166 return 0;
167 }
168
write_headers(hnd_t handle,x264_nal_t * p_nal)169 static int write_headers( hnd_t handle, x264_nal_t *p_nal )
170 {
171 flv_hnd_t *p_flv = handle;
172 flv_buffer *c = p_flv->c;
173
174 int sps_size = p_nal[0].i_payload;
175 int pps_size = p_nal[1].i_payload;
176 int sei_size = p_nal[2].i_payload;
177
178 // SEI
179 /* It is within the spec to write this as-is but for
180 * mplayer/ffmpeg playback this is deferred until before the first frame */
181
182 p_flv->sei = malloc( sei_size );
183 if( !p_flv->sei )
184 return -1;
185 p_flv->sei_len = sei_size;
186
187 memcpy( p_flv->sei, p_nal[2].p_payload, sei_size );
188
189 // SPS
190 uint8_t *sps = p_nal[0].p_payload + 4;
191
192 flv_put_byte( c, FLV_TAG_TYPE_VIDEO );
193 flv_put_be24( c, 0 ); // rewrite later
194 flv_put_be24( c, 0 ); // timestamp
195 flv_put_byte( c, 0 ); // timestamp extended
196 flv_put_be24( c, 0 ); // StreamID - Always 0
197 p_flv->start = c->d_cur; // needed for overwriting length
198
199 flv_put_byte( c, FLV_FRAME_KEY | FLV_CODECID_H264 ); // FrameType and CodecID
200 flv_put_byte( c, 0 ); // AVC sequence header
201 flv_put_be24( c, 0 ); // composition time
202
203 flv_put_byte( c, 1 ); // version
204 flv_put_byte( c, sps[1] ); // profile
205 flv_put_byte( c, sps[2] ); // profile
206 flv_put_byte( c, sps[3] ); // level
207 flv_put_byte( c, 0xff ); // 6 bits reserved (111111) + 2 bits nal size length - 1 (11)
208 flv_put_byte( c, 0xe1 ); // 3 bits reserved (111) + 5 bits number of sps (00001)
209
210 flv_put_be16( c, sps_size - 4 );
211 flv_append_data( c, sps, sps_size - 4 );
212
213 // PPS
214 flv_put_byte( c, 1 ); // number of pps
215 flv_put_be16( c, pps_size - 4 );
216 flv_append_data( c, p_nal[1].p_payload + 4, pps_size - 4 );
217
218 // rewrite data length info
219 unsigned length = c->d_cur - p_flv->start;
220 flv_rewrite_amf_be24( c, length, p_flv->start - 10 );
221 flv_put_be32( c, length + 11 ); // Last tag size
222 CHECK( flv_flush_data( c ) );
223
224 return sei_size + sps_size + pps_size;
225 }
226
write_frame(hnd_t handle,uint8_t * p_nalu,int i_size,x264_picture_t * p_picture)227 static int write_frame( hnd_t handle, uint8_t *p_nalu, int i_size, x264_picture_t *p_picture )
228 {
229 flv_hnd_t *p_flv = handle;
230 flv_buffer *c = p_flv->c;
231
232 #define convert_timebase_ms( timestamp, timebase ) (int64_t)((timestamp) * (timebase) * 1000 + 0.5)
233
234 if( !p_flv->i_framenum )
235 {
236 p_flv->i_delay_time = p_picture->i_dts * -1;
237 if( !p_flv->b_dts_compress && p_flv->i_delay_time )
238 x264_cli_log( "flv", X264_LOG_INFO, "initial delay %"PRId64" ms\n",
239 convert_timebase_ms( p_picture->i_pts + p_flv->i_delay_time, p_flv->d_timebase ) );
240 }
241
242 int64_t dts;
243 int64_t cts;
244 int64_t offset;
245
246 if( p_flv->b_dts_compress )
247 {
248 if( p_flv->i_framenum == 1 )
249 p_flv->i_init_delta = convert_timebase_ms( p_picture->i_dts + p_flv->i_delay_time, p_flv->d_timebase );
250 dts = p_flv->i_framenum > p_flv->i_delay_frames
251 ? convert_timebase_ms( p_picture->i_dts, p_flv->d_timebase )
252 : p_flv->i_framenum * p_flv->i_init_delta / (p_flv->i_delay_frames + 1);
253 cts = convert_timebase_ms( p_picture->i_pts, p_flv->d_timebase );
254 }
255 else
256 {
257 dts = convert_timebase_ms( p_picture->i_dts + p_flv->i_delay_time, p_flv->d_timebase );
258 cts = convert_timebase_ms( p_picture->i_pts + p_flv->i_delay_time, p_flv->d_timebase );
259 }
260 offset = cts - dts;
261
262 if( p_flv->i_framenum )
263 {
264 if( p_flv->i_prev_dts == dts )
265 x264_cli_log( "flv", X264_LOG_WARNING, "duplicate DTS %"PRId64" generated by rounding\n"
266 " decoding framerate cannot exceed 1000fps\n", dts );
267 if( p_flv->i_prev_cts == cts )
268 x264_cli_log( "flv", X264_LOG_WARNING, "duplicate CTS %"PRId64" generated by rounding\n"
269 " composition framerate cannot exceed 1000fps\n", cts );
270 }
271 p_flv->i_prev_dts = dts;
272 p_flv->i_prev_cts = cts;
273
274 // A new frame - write packet header
275 flv_put_byte( c, FLV_TAG_TYPE_VIDEO );
276 flv_put_be24( c, 0 ); // calculated later
277 flv_put_be24( c, dts );
278 flv_put_byte( c, dts >> 24 );
279 flv_put_be24( c, 0 );
280
281 p_flv->start = c->d_cur;
282 flv_put_byte( c, (p_picture->b_keyframe ? FLV_FRAME_KEY : FLV_FRAME_INTER) | FLV_CODECID_H264 );
283 flv_put_byte( c, 1 ); // AVC NALU
284 flv_put_be24( c, offset );
285
286 if( p_flv->sei )
287 {
288 flv_append_data( c, p_flv->sei, p_flv->sei_len );
289 free( p_flv->sei );
290 p_flv->sei = NULL;
291 }
292 flv_append_data( c, p_nalu, i_size );
293
294 unsigned length = c->d_cur - p_flv->start;
295 flv_rewrite_amf_be24( c, length, p_flv->start - 10 );
296 flv_put_be32( c, 11 + length ); // Last tag size
297 CHECK( flv_flush_data( c ) );
298
299 p_flv->i_framenum++;
300
301 return i_size;
302 }
303
rewrite_amf_double(FILE * fp,uint64_t position,double value)304 static int rewrite_amf_double( FILE *fp, uint64_t position, double value )
305 {
306 uint64_t x = endian_fix64( flv_dbl2int( value ) );
307 return !fseek( fp, position, SEEK_SET ) && fwrite( &x, 8, 1, fp ) == 1 ? 0 : -1;
308 }
309
310 #undef CHECK
311 #define CHECK(x)\
312 do {\
313 if( (x) < 0 )\
314 goto error;\
315 } while( 0 )
316
close_file(hnd_t handle,int64_t largest_pts,int64_t second_largest_pts)317 static int close_file( hnd_t handle, int64_t largest_pts, int64_t second_largest_pts )
318 {
319 int ret = -1;
320 flv_hnd_t *p_flv = handle;
321 flv_buffer *c = p_flv->c;
322
323 CHECK( flv_flush_data( c ) );
324
325 double total_duration;
326 /* duration algorithm fails with one frame */
327 if( p_flv->i_framenum == 1 )
328 total_duration = p_flv->i_fps_num ? (double)p_flv->i_fps_den / p_flv->i_fps_num : 0;
329 else
330 total_duration = (2 * largest_pts - second_largest_pts) * p_flv->d_timebase;
331
332 if( x264_is_regular_file( c->fp ) && total_duration > 0 )
333 {
334 double framerate;
335 int64_t filesize = ftell( c->fp );
336
337 if( p_flv->i_framerate_pos )
338 {
339 framerate = (double)p_flv->i_framenum / total_duration;
340 CHECK( rewrite_amf_double( c->fp, p_flv->i_framerate_pos, framerate ) );
341 }
342
343 CHECK( rewrite_amf_double( c->fp, p_flv->i_duration_pos, total_duration ) );
344 CHECK( rewrite_amf_double( c->fp, p_flv->i_filesize_pos, filesize ) );
345 CHECK( rewrite_amf_double( c->fp, p_flv->i_bitrate_pos, filesize * 8.0 / ( total_duration * 1000 ) ) );
346 }
347 ret = 0;
348
349 error:
350 fclose( c->fp );
351 free( c->data );
352 free( c );
353 free( p_flv );
354
355 return ret;
356 }
357
358 const cli_output_t flv_output = { open_file, set_param, write_headers, write_frame, close_file };
359