]> git.sesse.net Git - x264/blob - output/flv.c
aarch64: NEON asm for intra chroma deblocking
[x264] / output / flv.c
1 /*****************************************************************************
2  * flv.c: flv muxer
3  *****************************************************************************
4  * Copyright (C) 2009-2014 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
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
76 static int open_file( char *psz_filename, hnd_t *p_handle, cli_output_opt_t *opt )
77 {
78     *p_handle = NULL;
79     flv_hnd_t *p_flv = calloc( 1, sizeof(flv_hnd_t) );
80     if( !p_flv )
81         return -1;
82
83     p_flv->b_dts_compress = opt->use_dts_compress;
84
85     p_flv->c = flv_create_writer( psz_filename );
86     if( !p_flv->c )
87         return -1;
88
89     CHECK( write_header( p_flv->c ) );
90     *p_handle = p_flv;
91
92     return 0;
93 }
94
95 static int set_param( hnd_t handle, x264_param_t *p_param )
96 {
97     flv_hnd_t *p_flv = handle;
98     flv_buffer *c = p_flv->c;
99
100     flv_put_byte( c, FLV_TAG_TYPE_META ); // Tag Type "script data"
101
102     int start = c->d_cur;
103     flv_put_be24( c, 0 ); // data length
104     flv_put_be24( c, 0 ); // timestamp
105     flv_put_be32( c, 0 ); // reserved
106
107     flv_put_byte( c, AMF_DATA_TYPE_STRING );
108     flv_put_amf_string( c, "onMetaData" );
109
110     flv_put_byte( c, AMF_DATA_TYPE_MIXEDARRAY );
111     flv_put_be32( c, 7 );
112
113     flv_put_amf_string( c, "width" );
114     flv_put_amf_double( c, p_param->i_width );
115
116     flv_put_amf_string( c, "height" );
117     flv_put_amf_double( c, p_param->i_height );
118
119     flv_put_amf_string( c, "framerate" );
120
121     if( !p_param->b_vfr_input )
122         flv_put_amf_double( c, (double)p_param->i_fps_num / p_param->i_fps_den );
123     else
124     {
125         p_flv->i_framerate_pos = c->d_cur + c->d_total + 1;
126         flv_put_amf_double( c, 0 ); // written at end of encoding
127     }
128
129     flv_put_amf_string( c, "videocodecid" );
130     flv_put_amf_double( c, FLV_CODECID_H264 );
131
132     flv_put_amf_string( c, "duration" );
133     p_flv->i_duration_pos = c->d_cur + c->d_total + 1;
134     flv_put_amf_double( c, 0 ); // written at end of encoding
135
136     flv_put_amf_string( c, "filesize" );
137     p_flv->i_filesize_pos = c->d_cur + c->d_total + 1;
138     flv_put_amf_double( c, 0 ); // written at end of encoding
139
140     flv_put_amf_string( c, "videodatarate" );
141     p_flv->i_bitrate_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, "" );
145     flv_put_byte( c, AMF_END_OF_OBJECT );
146
147     unsigned length = c->d_cur - start;
148     flv_rewrite_amf_be24( c, length - 10, start );
149
150     flv_put_be32( c, length + 1 ); // tag length
151
152     p_flv->i_fps_num = p_param->i_fps_num;
153     p_flv->i_fps_den = p_param->i_fps_den;
154     p_flv->d_timebase = (double)p_param->i_timebase_num / p_param->i_timebase_den;
155     p_flv->b_vfr_input = p_param->b_vfr_input;
156     p_flv->i_delay_frames = p_param->i_bframe ? (p_param->i_bframe_pyramid ? 2 : 1) : 0;
157
158     return 0;
159 }
160
161 static int write_headers( hnd_t handle, x264_nal_t *p_nal )
162 {
163     flv_hnd_t *p_flv = handle;
164     flv_buffer *c = p_flv->c;
165
166     int sps_size = p_nal[0].i_payload;
167     int pps_size = p_nal[1].i_payload;
168     int sei_size = p_nal[2].i_payload;
169
170     // SEI
171     /* It is within the spec to write this as-is but for
172      * mplayer/ffmpeg playback this is deferred until before the first frame */
173
174     p_flv->sei = malloc( sei_size );
175     if( !p_flv->sei )
176         return -1;
177     p_flv->sei_len = sei_size;
178
179     memcpy( p_flv->sei, p_nal[2].p_payload, sei_size );
180
181     // SPS
182     uint8_t *sps = p_nal[0].p_payload + 4;
183
184     flv_put_byte( c, FLV_TAG_TYPE_VIDEO );
185     flv_put_be24( c, 0 ); // rewrite later
186     flv_put_be24( c, 0 ); // timestamp
187     flv_put_byte( c, 0 ); // timestamp extended
188     flv_put_be24( c, 0 ); // StreamID - Always 0
189     p_flv->start = c->d_cur; // needed for overwriting length
190
191     flv_put_byte( c, 7 | FLV_FRAME_KEY ); // Frametype and CodecID
192     flv_put_byte( c, 0 ); // AVC sequence header
193     flv_put_be24( c, 0 ); // composition time
194
195     flv_put_byte( c, 1 );      // version
196     flv_put_byte( c, sps[1] ); // profile
197     flv_put_byte( c, sps[2] ); // profile
198     flv_put_byte( c, sps[3] ); // level
199     flv_put_byte( c, 0xff );   // 6 bits reserved (111111) + 2 bits nal size length - 1 (11)
200     flv_put_byte( c, 0xe1 );   // 3 bits reserved (111) + 5 bits number of sps (00001)
201
202     flv_put_be16( c, sps_size - 4 );
203     flv_append_data( c, sps, sps_size - 4 );
204
205     // PPS
206     flv_put_byte( c, 1 ); // number of pps
207     flv_put_be16( c, pps_size - 4 );
208     flv_append_data( c, p_nal[1].p_payload + 4, pps_size - 4 );
209
210     // rewrite data length info
211     unsigned length = c->d_cur - p_flv->start;
212     flv_rewrite_amf_be24( c, length, p_flv->start - 10 );
213     flv_put_be32( c, length + 11 ); // Last tag size
214     CHECK( flv_flush_data( c ) );
215
216     return sei_size + sps_size + pps_size;
217 }
218
219 static int write_frame( hnd_t handle, uint8_t *p_nalu, int i_size, x264_picture_t *p_picture )
220 {
221     flv_hnd_t *p_flv = handle;
222     flv_buffer *c = p_flv->c;
223
224 #define convert_timebase_ms( timestamp, timebase ) (int64_t)((timestamp) * (timebase) * 1000 + 0.5)
225
226     if( !p_flv->i_framenum )
227     {
228         p_flv->i_delay_time = p_picture->i_dts * -1;
229         if( !p_flv->b_dts_compress && p_flv->i_delay_time )
230             x264_cli_log( "flv", X264_LOG_INFO, "initial delay %"PRId64" ms\n",
231                           convert_timebase_ms( p_picture->i_pts + p_flv->i_delay_time, p_flv->d_timebase ) );
232     }
233
234     int64_t dts;
235     int64_t cts;
236     int64_t offset;
237
238     if( p_flv->b_dts_compress )
239     {
240         if( p_flv->i_framenum == 1 )
241             p_flv->i_init_delta = convert_timebase_ms( p_picture->i_dts + p_flv->i_delay_time, p_flv->d_timebase );
242         dts = p_flv->i_framenum > p_flv->i_delay_frames
243             ? convert_timebase_ms( p_picture->i_dts, p_flv->d_timebase )
244             : p_flv->i_framenum * p_flv->i_init_delta / (p_flv->i_delay_frames + 1);
245         cts = convert_timebase_ms( p_picture->i_pts, p_flv->d_timebase );
246     }
247     else
248     {
249         dts = convert_timebase_ms( p_picture->i_dts + p_flv->i_delay_time, p_flv->d_timebase );
250         cts = convert_timebase_ms( p_picture->i_pts + p_flv->i_delay_time, p_flv->d_timebase );
251     }
252     offset = cts - dts;
253
254     if( p_flv->i_framenum )
255     {
256         if( p_flv->i_prev_dts == dts )
257             x264_cli_log( "flv", X264_LOG_WARNING, "duplicate DTS %"PRId64" generated by rounding\n"
258                           "               decoding framerate cannot exceed 1000fps\n", dts );
259         if( p_flv->i_prev_cts == cts )
260             x264_cli_log( "flv", X264_LOG_WARNING, "duplicate CTS %"PRId64" generated by rounding\n"
261                           "               composition framerate cannot exceed 1000fps\n", cts );
262     }
263     p_flv->i_prev_dts = dts;
264     p_flv->i_prev_cts = cts;
265
266     // A new frame - write packet header
267     flv_put_byte( c, FLV_TAG_TYPE_VIDEO );
268     flv_put_be24( c, 0 ); // calculated later
269     flv_put_be24( c, dts );
270     flv_put_byte( c, dts >> 24 );
271     flv_put_be24( c, 0 );
272
273     p_flv->start = c->d_cur;
274     flv_put_byte( c, p_picture->b_keyframe ? FLV_FRAME_KEY : FLV_FRAME_INTER );
275     flv_put_byte( c, 1 ); // AVC NALU
276     flv_put_be24( c, offset );
277
278     if( p_flv->sei )
279     {
280         flv_append_data( c, p_flv->sei, p_flv->sei_len );
281         free( p_flv->sei );
282         p_flv->sei = NULL;
283     }
284     flv_append_data( c, p_nalu, i_size );
285
286     unsigned length = c->d_cur - p_flv->start;
287     flv_rewrite_amf_be24( c, length, p_flv->start - 10 );
288     flv_put_be32( c, 11 + length ); // Last tag size
289     CHECK( flv_flush_data( c ) );
290
291     p_flv->i_framenum++;
292
293     return i_size;
294 }
295
296 static void rewrite_amf_double( FILE *fp, uint64_t position, double value )
297 {
298     uint64_t x = endian_fix64( flv_dbl2int( value ) );
299     fseek( fp, position, SEEK_SET );
300     fwrite( &x, 8, 1, fp );
301 }
302
303 static int close_file( hnd_t handle, int64_t largest_pts, int64_t second_largest_pts )
304 {
305     flv_hnd_t *p_flv = handle;
306     flv_buffer *c = p_flv->c;
307
308     CHECK( flv_flush_data( c ) );
309
310     double total_duration = (2 * largest_pts - second_largest_pts) * p_flv->d_timebase;
311
312     if( x264_is_regular_file( c->fp ) && total_duration > 0 )
313     {
314         double framerate;
315         uint64_t filesize = ftell( c->fp );
316
317         if( p_flv->i_framerate_pos )
318         {
319             framerate = (double)p_flv->i_framenum / total_duration;
320             rewrite_amf_double( c->fp, p_flv->i_framerate_pos, framerate );
321         }
322
323         rewrite_amf_double( c->fp, p_flv->i_duration_pos, total_duration );
324         rewrite_amf_double( c->fp, p_flv->i_filesize_pos, filesize );
325         rewrite_amf_double( c->fp, p_flv->i_bitrate_pos, filesize * 8 / ( total_duration * 1000 ) );
326     }
327
328     fclose( c->fp );
329     free( p_flv );
330     free( c );
331
332     return 0;
333 }
334
335 const cli_output_t flv_output = { open_file, set_param, write_headers, write_frame, close_file };