1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2009 Kieran Kunhya
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
19 *****************************************************************************/
22 #include "flv_bytestream.h"
44 uint64_t i_duration_pos;
45 uint64_t i_filesize_pos;
46 uint64_t i_bitrate_pos;
48 uint8_t b_write_length;
53 static int write_header( flv_buffer *c )
55 x264_put_tag( c, "FLV" ); // Signature
56 x264_put_byte( c, 1 ); // Version
57 x264_put_byte( c, 1 ); // Video Only
58 x264_put_be32( c, 9 ); // DataOffset
59 x264_put_be32( c, 0 ); // PreviousTagSize0
61 return flv_flush_data( c );
64 static int open_file( char *psz_filename, hnd_t *p_handle )
66 flv_hnd_t *p_flv = malloc( sizeof(*p_flv) );
70 memset( p_flv, 0, sizeof(*p_flv) );
72 p_flv->c = flv_create_writer( psz_filename );
76 CHECK( write_header( p_flv->c ) );
82 static int set_param( hnd_t handle, x264_param_t *p_param )
84 flv_hnd_t *p_flv = handle;
85 flv_buffer *c = p_flv->c;
87 x264_put_byte( c, FLV_TAG_TYPE_META ); // Tag Type "script data"
90 x264_put_be24( c, 0 ); // data length
91 x264_put_be24( c, 0 ); // timestamp
92 x264_put_be32( c, 0 ); // reserved
94 x264_put_byte( c, AMF_DATA_TYPE_STRING );
95 x264_put_amf_string( c, "onMetaData" );
97 x264_put_byte( c, AMF_DATA_TYPE_MIXEDARRAY );
98 x264_put_be32( c, 7 );
100 x264_put_amf_string( c, "width" );
101 x264_put_amf_double( c, p_param->i_width );
103 x264_put_amf_string( c, "height" );
104 x264_put_amf_double( c, p_param->i_height );
106 x264_put_amf_string( c, "framerate" );
107 x264_put_amf_double( c, (double)p_param->i_fps_num / p_param->i_fps_den );
109 x264_put_amf_string( c, "videocodecid" );
110 x264_put_amf_double( c, FLV_CODECID_H264 );
112 x264_put_amf_string( c, "duration" );
113 p_flv->i_duration_pos = c->d_cur + c->d_total + 1; // + 1 because of the following AMF_DATA_TYPE_NUMBER byte
114 x264_put_amf_double( c, 0 ); // written at end of encoding
116 x264_put_amf_string( c, "filesize" );
117 p_flv->i_filesize_pos = c->d_cur + c->d_total + 1;
118 x264_put_amf_double( c, 0 ); // written at end of encoding
120 x264_put_amf_string( c, "videodatarate" );
121 p_flv->i_bitrate_pos = c->d_cur + c->d_total + 1;
122 x264_put_amf_double( c, 0 ); // written at end of encoding
124 x264_put_amf_string( c, "" );
125 x264_put_byte( c, AMF_END_OF_OBJECT );
127 unsigned length = c->d_cur - start;
128 rewrite_amf_be24( c, length - 10, start );
130 x264_put_be32( c, length + 1 ); // tag length
132 p_flv->i_fps_num = p_param->i_fps_num;
133 p_flv->i_fps_den = p_param->i_fps_den;
134 p_flv->i_init_delay = p_param->i_bframe ? (p_param->i_bframe_pyramid ? 2 : 1) : 0;
135 p_flv->d_mspf = 1000 * (double)p_flv->i_fps_den / p_flv->i_fps_num;
137 fprintf( stderr, "flv [info]: initial delay %i frames\n",
138 (int)p_flv->i_init_delay );
143 static int write_nalu( hnd_t handle, uint8_t *p_nalu, int i_size, x264_picture_t *p_picture )
145 flv_hnd_t *p_flv = handle;
146 flv_buffer *c = p_flv->c;
147 uint64_t dts = (uint64_t)p_flv->i_framenum * p_flv->d_mspf;
148 uint64_t pts = (uint64_t)p_picture->i_pts * p_flv->d_mspf / p_flv->i_fps_den;
149 uint64_t offset = p_flv->i_init_delay * p_flv->d_mspf + pts - dts;
150 uint8_t type = p_nalu[4] & 0x1f;
158 uint8_t *sps = p_nalu + 4;
160 x264_put_byte( c, FLV_TAG_TYPE_VIDEO );
161 x264_put_be24( c, 0 ); // rewrite later, pps size unknown
162 x264_put_be24( c, 0 ); // timestamp
163 x264_put_byte( c, 0 ); // timestamp extended
164 x264_put_be24( c, 0 ); // StreamID - Always 0
165 p_flv->start = c->d_cur; // needed for overwriting length
167 x264_put_byte( c, 7 | FLV_FRAME_KEY ); // Frametype and CodecID
168 x264_put_byte( c, 0 ); // AVC sequence header
169 x264_put_be24( c, 0 ); // composition time
171 x264_put_byte( c, 1 ); // version
172 x264_put_byte( c, sps[1] ); // profile
173 x264_put_byte( c, sps[2] ); // profile
174 x264_put_byte( c, sps[3] ); // level
175 x264_put_byte( c, 0xff ); // 6 bits reserved (111111) + 2 bits nal size length - 1 (11)
176 x264_put_byte( c, 0xe1 ); // 3 bits reserved (111) + 5 bits number of sps (00001)
178 x264_put_be16( c, i_size - 4 );
179 flv_append_data( c, sps, i_size - 4 );
189 x264_put_byte( c, 1 ); // number of pps
190 x264_put_be16( c, i_size - 4 );
191 flv_append_data( c, p_nalu + 4, i_size - 4 );
193 // rewrite data length info
194 unsigned length = c->d_cur - p_flv->start;
195 rewrite_amf_be24( c, length, p_flv->start - 10 );
196 x264_put_be32( c, length + 11 ); // Last tag size
205 if( !p_flv->b_write_length )
207 // A new frame - write packet header
208 x264_put_byte( c, FLV_TAG_TYPE_VIDEO );
209 x264_put_be24( c, 0 ); // calculated later
210 x264_put_be24( c, dts );
211 x264_put_byte( c, dts >> 24 );
212 x264_put_be24( c, 0 );
214 p_flv->start = c->d_cur;
215 x264_put_byte( c, p_picture->i_type == X264_TYPE_IDR ? FLV_FRAME_KEY : FLV_FRAME_INTER );
216 x264_put_byte( c, 1 ); // AVC NALU
217 x264_put_be24( c, offset );
219 p_flv->b_write_length = 1;
223 flv_append_data( c, p_flv->sei, p_flv->sei_len );
227 flv_append_data( c, p_nalu, i_size );
231 /* It is within the spec to write this as-is but for
232 * mplayer/ffmpeg playback this is deferred until before the first frame */
234 p_flv->sei = malloc( i_size );
237 p_flv->sei_len = i_size;
239 memcpy( p_flv->sei, p_nalu, i_size );
245 static int set_eop( hnd_t handle, x264_picture_t *p_picture )
247 flv_hnd_t *p_flv = handle;
248 flv_buffer *c = p_flv->c;
250 if( p_flv->b_write_length )
252 unsigned length = c->d_cur - p_flv->start;
253 rewrite_amf_be24( c, length, p_flv->start - 10 );
254 x264_put_be32( c, 11 + length ); // Last tag size
255 CHECK( flv_flush_data( c ) );
256 p_flv->b_write_length = 0;
263 static void rewrite_amf_double( FILE *fp, uint64_t position, double value )
265 uint64_t x = endian_fix64( dbl2int( value ) );
266 fseek( fp, position, SEEK_SET );
267 fwrite( &x, 8, 1, fp );
270 static int close_file( hnd_t handle )
272 flv_hnd_t *p_flv = handle;
273 flv_buffer *c = p_flv->c;
275 CHECK( flv_flush_data( c ) );
277 if( x264_is_regular_file( c->fp ) )
279 double duration = p_flv->i_fps_den * p_flv->i_framenum / p_flv->i_fps_num;
280 uint64_t filesize = ftell( c->fp );
281 rewrite_amf_double( c->fp, p_flv->i_duration_pos, duration );
282 rewrite_amf_double( c->fp, p_flv->i_filesize_pos, filesize );
283 rewrite_amf_double( c->fp, p_flv->i_bitrate_pos, filesize * 8 / ( duration * 1000 ) );
293 cli_output_t flv_output = { open_file, set_param, write_nalu, set_eop, close_file };