pts fix / b frame segfault fix
[libav.git] / libavformat / flvenc.c
CommitLineData
d4f5d74a
GM
1/*
2 * FLV encoder.
3 * Copyright (c) 2003 The FFmpeg Project.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include "avformat.h"
20
068f2a22
MN
21#undef NDEBUG
22#include <assert.h>
23
d4f5d74a
GM
24#define VIDEO_FIFO_SIZE 512
25
26typedef struct FLVFrame {
27 int type;
28 int timestamp;
29 int flags;
30 uint8_t *data;
31 int size;
32 struct FLVFrame *next;
33} FLVFrame;
34
35typedef struct FLVContext {
36 int hasAudio;
37 int hasVideo;
d4f5d74a 38 int initDelay;
d4f5d74a 39 int64_t sampleCount;
d4f5d74a
GM
40 int64_t frameCount;
41 FLVFrame *frames;
42} FLVContext;
43
d4f5d74a
GM
44#ifdef CONFIG_MP3LAME
45
d4f5d74a
GM
46static const int sSampleRates[3][4] = {
47 {44100, 48000, 32000, 0},
48 {22050, 24000, 16000, 0},
49 {11025, 12000, 8000, 0},
50};
51
52static const int sBitRates[2][3][15] = {
53 { { 0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448},
54 { 0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384},
55 { 0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320}
56 },
57 { { 0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256},
58 { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160},
59 { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}
60 },
61};
62
63static const int sSamplesPerFrame[3][3] =
64{
65 { 384, 1152, 1152 },
66 { 384, 1152, 576 },
67 { 384, 1152, 576 }
68};
69
70static const int sBitsPerSlot[3] = {
71 32,
72 8,
73 8
74};
75
76static int mp3info(void *data, int *byteSize, int *samplesPerFrame, int *sampleRate, int *isMono )
77{
78 uint8_t *dataTmp = (uint8_t *)data;
79 uint32_t header = ( (uint32_t)dataTmp[0] << 24 ) | ( (uint32_t)dataTmp[1] << 16 ) | ( (uint32_t)dataTmp[2] << 8 ) | (uint32_t)dataTmp[3];
80 int layerID = 3 - ((header >> 17) & 0x03);
81 int bitRateID = ((header >> 12) & 0x0f);
82 int sampleRateID = ((header >> 10) & 0x03);
83 int bitRate = 0;
84 int bitsPerSlot = sBitsPerSlot[layerID];
85 int isPadded = ((header >> 9) & 0x01);
86
87 if ( (( header >> 21 ) & 0x7ff) != 0x7ff ) {
88 return 0;
89 }
90
91 if ( !isPadded ) {
92a26775
MN
92// printf("Fatal error: mp3 data is not padded!\n");
93// exit(0);
d4f5d74a
GM
94 }
95
96 *isMono = ((header >> 6) & 0x03) == 0x03;
97
98 if ( (header >> 19 ) & 0x01 ) {
92a26775 99 //MPEG1
d4f5d74a
GM
100 *sampleRate = sSampleRates[0][sampleRateID];
101 bitRate = sBitRates[0][layerID][bitRateID] * 1000;
102 *samplesPerFrame = sSamplesPerFrame[0][layerID];
d4f5d74a
GM
103 } else {
104 if ( (header >> 20) & 0x01 ) {
92a26775 105 //MPEG2
d4f5d74a
GM
106 *sampleRate = sSampleRates[1][sampleRateID];
107 bitRate = sBitRates[1][layerID][bitRateID] * 1000;
108 *samplesPerFrame = sSamplesPerFrame[1][layerID];
109 } else {
92a26775 110 //MPEG2.5
d4f5d74a
GM
111 *sampleRate = sSampleRates[2][sampleRateID];
112 bitRate = sBitRates[1][layerID][bitRateID] * 1000;
113 *samplesPerFrame = sSamplesPerFrame[2][layerID];
114 }
115 }
92a26775 116
747a0554 117 *byteSize = ( ( ( ( *samplesPerFrame * (bitRate / bitsPerSlot) ) / *sampleRate ) + isPadded ) );
d4f5d74a
GM
118 return 1;
119}
120#endif // CONFIG_MP3LAME
121
122static int flv_write_header(AVFormatContext *s)
123{
124 ByteIOContext *pb = &s->pb;
125 FLVContext *flv = s->priv_data;
126
127 av_set_pts_info(s, 24, 1, 1000); /* 24 bit pts in ms */
128
129 flv->hasAudio = 0;
130 flv->hasVideo = 0;
131
d4f5d74a 132 flv->initDelay = -1;
d4f5d74a
GM
133
134 flv->frames = 0;
135
136 put_tag(pb,"FLV");
137 put_byte(pb,1);
138 put_byte(pb,0); // delayed write
139 put_be32(pb,9);
140 put_be32(pb,0);
141
142 return 0;
143}
144
145static void put_be24(ByteIOContext *pb, int value)
146{
147 put_byte(pb, (value>>16) & 0xFF );
148 put_byte(pb, (value>> 8) & 0xFF );
149 put_byte(pb, (value>> 0) & 0xFF );
150}
151
152static void InsertSorted(FLVContext *flv, FLVFrame *frame)
153{
154 if ( !flv->frames ) {
155 flv->frames = frame;
156 } else {
157 FLVFrame *trav = flv->frames;
158 FLVFrame *prev = 0;
159 for (;trav;) {
160 if ( trav->timestamp >= frame->timestamp ) {
161 frame->next = trav;
162 if ( prev ) {
163 prev->next = frame;
164 } else {
165 flv->frames = frame;
166 }
167 break;
168 }
169 prev = trav;
170 trav = trav->next;
171 }
172 if ( !trav ) {
173 prev->next = frame;
174 }
175 }
176}
177
178static void DumpFrame(ByteIOContext *pb, FLVFrame *frame)
179{
180 put_byte(pb,frame->type); // message type
181 put_be24(pb,frame->size+1); // include flags
182 put_be24(pb,frame->timestamp); // time stamp
183 put_be32(pb,0); // reserved
184 put_byte(pb,frame->flags);
185 put_buffer(pb, frame->data, frame->size);
186 put_be32(pb,frame->size+1+11); // reserved
187 av_free(frame->data);
188}
189
190static void Dump(FLVContext *flv, ByteIOContext *pb, int count)
191{
192 int c=0;
193 FLVFrame *trav = flv->frames;
194 FLVFrame *prev = 0;
195 for (;trav;c++) {
196 trav = trav->next;
197 }
198 trav = flv->frames;
199 for ( ; c >= count; c-- ) {
200 DumpFrame(pb,trav);
201 prev = trav;
202 trav = trav->next;
203 av_free(prev);
204 }
205 flv->frames = trav;
206}
207
208static int flv_write_trailer(AVFormatContext *s)
209{
14b32253
MN
210 int64_t file_size;
211 int flags = 0;
212
d4f5d74a
GM
213 ByteIOContext *pb = &s->pb;
214 FLVContext *flv = s->priv_data;
215
216 Dump(flv,pb,1);
217
14b32253 218 file_size = url_ftell(pb);
d4f5d74a
GM
219 flags |= flv->hasAudio ? 4 : 0;
220 flags |= flv->hasVideo ? 1 : 0;
221 url_fseek(pb, 4, SEEK_SET);
222 put_byte(pb,flags);
223 url_fseek(pb, file_size, SEEK_SET);
224 return 0;
225}
226
227static int flv_write_packet(AVFormatContext *s, int stream_index,
49057904 228 const uint8_t *buf, int size, int64_t timestamp)
d4f5d74a
GM
229{
230 ByteIOContext *pb = &s->pb;
231 AVCodecContext *enc = &s->streams[stream_index]->codec;
232 FLVContext *flv = s->priv_data;
068f2a22 233 FLVFrame *frame = av_malloc(sizeof(FLVFrame));
d4f5d74a 234
068f2a22
MN
235 frame->next = 0;
236 frame->size = size;
237 frame->data = av_malloc(size);
238 frame->timestamp = timestamp;
239 memcpy(frame->data,buf,size);
240
241// av_log(s, AV_LOG_DEBUG, "type:%d pts: %lld size:%d\n", enc->codec_type, timestamp, size);
242
d4f5d74a 243 if (enc->codec_type == CODEC_TYPE_VIDEO) {
d4f5d74a
GM
244 frame->type = 9;
245 frame->flags = 2; // choose h263
246 frame->flags |= enc->coded_frame->key_frame ? 0x10 : 0x20; // add keyframe indicator
d4f5d74a
GM
247 //frame->timestamp = ( ( flv->frameCount * (int64_t)FRAME_RATE_BASE * (int64_t)1000 ) / (int64_t)enc->frame_rate );
248 //printf("%08x %f %f\n",frame->timestamp,(double)enc->frame_rate/(double)FRAME_RATE_BASE,1000*(double)FRAME_RATE_BASE/(double)enc->frame_rate);
d4f5d74a
GM
249 flv->hasVideo = 1;
250
251 InsertSorted(flv,frame);
252
253 flv->frameCount ++;
254 }
255 else if (enc->codec_type == CODEC_TYPE_AUDIO) {
068f2a22 256 int soundFormat = 0x02;
92a26775 257
068f2a22
MN
258 switch (enc->sample_rate) {
259 case 44100:
260 soundFormat |= 0x0C;
261 break;
262 case 22050:
263 soundFormat |= 0x08;
264 break;
265 case 11025:
266 soundFormat |= 0x04;
267 break;
268 case 8000: //nellymoser only
269 case 5512: //not mp3
270 soundFormat |= 0x00;
271 break;
272 default:
273 assert(0);
274 }
d4f5d74a 275
068f2a22
MN
276 if (enc->channels > 1) {
277 soundFormat |= 0x01;
278 }
279
280 switch(enc->codec_id){
281 case CODEC_ID_MP3:
282 soundFormat |= 0x20;
283 break;
284 case 0:
285 soundFormat |= enc->codec_tag<<4;
286 break;
287 default:
288 assert(0);
289 }
290
291 assert(size);
292 if ( flv->initDelay == -1 ) {
293 flv->initDelay = timestamp;
294 }
295
296 frame->type = 8;
297 frame->flags = soundFormat;
d4f5d74a 298
92a26775 299// if ( flv->audioTime == -1 ) {
d4f5d74a
GM
300// flv->audioTime = ( ( ( flv->sampleCount - enc->delay ) * 8000 ) / flv->audioRate ) - flv->initDelay - 250;
301// if ( flv->audioTime < 0 ) {
302// flv->audioTime = 0;
303// }
92a26775 304// }
d4f5d74a 305
068f2a22
MN
306#ifdef CONFIG_MP3LAME
307 if (enc->codec_id == CODEC_ID_MP3 ) {
d4f5d74a
GM
308 int mp3FrameSize = 0;
309 int mp3SampleRate = 0;
310 int mp3IsMono = 0;
311 int mp3SamplesPerFrame = 0;
747a0554
TU
312
313 /* copy out mp3 header from ring buffer */
068f2a22
MN
314 if(!mp3info(buf,&mp3FrameSize,&mp3SamplesPerFrame,&mp3SampleRate,&mp3IsMono))
315 assert(0);
316 assert ( size == mp3FrameSize );
317 assert(enc->sample_rate == mp3SampleRate);
318// assert(enc->frame_size == mp3SamplesPerFrame);
319//av_log(NULL, AV_LOG_DEBUG, "sizes: %d %d\n", enc->frame_size, mp3SamplesPerFrame);
320
321 frame->timestamp = (1000*flv->sampleCount + enc->sample_rate/2)/(enc->sample_rate);
322 flv->sampleCount += mp3SamplesPerFrame;
d4f5d74a
GM
323 }
324#endif
068f2a22
MN
325
326 // We got audio! Make sure we set this to the global flags on closure
327 flv->hasAudio = 1;
328 InsertSorted(flv,frame);
329 }else
330 assert(0);
d4f5d74a
GM
331 Dump(flv,pb,128);
332 put_flush_packet(pb);
333 return 0;
334}
335
336static AVOutputFormat flv_oformat = {
337 "flv",
338 "flv format",
339 "video/x-flashvideo",
340 "flv",
341 sizeof(FLVContext),
342#ifdef CONFIG_MP3LAME
80783dc2 343 CODEC_ID_MP3,
d4f5d74a
GM
344#else // CONFIG_MP3LAME
345 CODEC_ID_NONE,
346#endif // CONFIG_MP3LAME
347 CODEC_ID_FLV1,
348 flv_write_header,
349 flv_write_packet,
350 flv_write_trailer,
351};
352
353int flvenc_init(void)
354{
355 av_register_output_format(&flv_oformat);
356 return 0;
357}