Mercurial > libavformat.hg
comparison flvenc.c @ 445:c1f88671135b libavformat
cleanup
fix streamcopy
author | michael |
---|---|
date | Sat, 17 Apr 2004 12:04:59 +0000 |
parents | 20f644245408 |
children | 35447449b8b4 |
comparison
equal
deleted
inserted
replaced
444:d42038d418a0 | 445:c1f88671135b |
---|---|
16 * License along with this library; if not, write to the Free Software | 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 | 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 */ | 18 */ |
19 #include "avformat.h" | 19 #include "avformat.h" |
20 | 20 |
21 #undef NDEBUG | |
22 #include <assert.h> | |
23 | |
21 #define VIDEO_FIFO_SIZE 512 | 24 #define VIDEO_FIFO_SIZE 512 |
22 | 25 |
23 typedef struct FLVFrame { | 26 typedef struct FLVFrame { |
24 int type; | 27 int type; |
25 int timestamp; | 28 int timestamp; |
30 } FLVFrame; | 33 } FLVFrame; |
31 | 34 |
32 typedef struct FLVContext { | 35 typedef struct FLVContext { |
33 int hasAudio; | 36 int hasAudio; |
34 int hasVideo; | 37 int hasVideo; |
35 #ifdef CONFIG_MP3LAME | |
36 int audioTime; | |
37 int audioInPos; | |
38 int audioOutPos; | |
39 int audioSize; | |
40 // int audioRate; | |
41 int initDelay; | 38 int initDelay; |
42 int soundDelay; | |
43 uint8_t *audioFifo; | |
44 int64_t sampleCount; | 39 int64_t sampleCount; |
45 #endif // CONFIG_MP3LAME | |
46 int64_t frameCount; | 40 int64_t frameCount; |
47 FLVFrame *frames; | 41 FLVFrame *frames; |
48 } FLVContext; | 42 } FLVContext; |
49 | 43 |
50 | |
51 #ifdef CONFIG_MP3LAME | 44 #ifdef CONFIG_MP3LAME |
52 | |
53 #define AUDIO_FIFO_SIZE 65536 | |
54 | 45 |
55 static const int sSampleRates[3][4] = { | 46 static const int sSampleRates[3][4] = { |
56 {44100, 48000, 32000, 0}, | 47 {44100, 48000, 32000, 0}, |
57 {22050, 24000, 16000, 0}, | 48 {22050, 24000, 16000, 0}, |
58 {11025, 12000, 8000, 0}, | 49 {11025, 12000, 8000, 0}, |
136 av_set_pts_info(s, 24, 1, 1000); /* 24 bit pts in ms */ | 127 av_set_pts_info(s, 24, 1, 1000); /* 24 bit pts in ms */ |
137 | 128 |
138 flv->hasAudio = 0; | 129 flv->hasAudio = 0; |
139 flv->hasVideo = 0; | 130 flv->hasVideo = 0; |
140 | 131 |
141 #ifdef CONFIG_MP3LAME | |
142 flv->audioTime = -1; | |
143 flv->audioFifo = av_malloc(AUDIO_FIFO_SIZE); | |
144 flv->audioInPos = 0; | |
145 flv->audioOutPos = 0; | |
146 flv->audioSize = 0; | |
147 // flv->audioRate = 44100; | |
148 flv->initDelay = -1; | 132 flv->initDelay = -1; |
149 flv->soundDelay = 0; | |
150 #endif // CONFIG_MP3LAME | |
151 | 133 |
152 flv->frames = 0; | 134 flv->frames = 0; |
153 | 135 |
154 put_tag(pb,"FLV"); | 136 put_tag(pb,"FLV"); |
155 put_byte(pb,1); | 137 put_byte(pb,1); |
246 const uint8_t *buf, int size, int64_t timestamp) | 228 const uint8_t *buf, int size, int64_t timestamp) |
247 { | 229 { |
248 ByteIOContext *pb = &s->pb; | 230 ByteIOContext *pb = &s->pb; |
249 AVCodecContext *enc = &s->streams[stream_index]->codec; | 231 AVCodecContext *enc = &s->streams[stream_index]->codec; |
250 FLVContext *flv = s->priv_data; | 232 FLVContext *flv = s->priv_data; |
251 | 233 FLVFrame *frame = av_malloc(sizeof(FLVFrame)); |
234 | |
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 | |
252 if (enc->codec_type == CODEC_TYPE_VIDEO) { | 243 if (enc->codec_type == CODEC_TYPE_VIDEO) { |
253 FLVFrame *frame = av_malloc(sizeof(FLVFrame)); | |
254 frame->next = 0; | |
255 frame->type = 9; | 244 frame->type = 9; |
256 frame->flags = 2; // choose h263 | 245 frame->flags = 2; // choose h263 |
257 frame->flags |= enc->coded_frame->key_frame ? 0x10 : 0x20; // add keyframe indicator | 246 frame->flags |= enc->coded_frame->key_frame ? 0x10 : 0x20; // add keyframe indicator |
258 frame->timestamp = timestamp; | |
259 //frame->timestamp = ( ( flv->frameCount * (int64_t)FRAME_RATE_BASE * (int64_t)1000 ) / (int64_t)enc->frame_rate ); | 247 //frame->timestamp = ( ( flv->frameCount * (int64_t)FRAME_RATE_BASE * (int64_t)1000 ) / (int64_t)enc->frame_rate ); |
260 //printf("%08x %f %f\n",frame->timestamp,(double)enc->frame_rate/(double)FRAME_RATE_BASE,1000*(double)FRAME_RATE_BASE/(double)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); |
261 frame->size = size; | |
262 frame->data = av_malloc(size); | |
263 memcpy(frame->data,buf,size); | |
264 flv->hasVideo = 1; | 249 flv->hasVideo = 1; |
265 | 250 |
266 InsertSorted(flv,frame); | 251 InsertSorted(flv,frame); |
267 | 252 |
268 flv->frameCount ++; | 253 flv->frameCount ++; |
269 } | 254 } |
270 else if (enc->codec_type == CODEC_TYPE_AUDIO) { | 255 else if (enc->codec_type == CODEC_TYPE_AUDIO) { |
271 #ifdef CONFIG_MP3LAME | 256 int soundFormat = 0x02; |
272 if (enc->codec_id == CODEC_ID_MP3 ) { | 257 |
273 int c=0; | 258 switch (enc->sample_rate) { |
274 | 259 case 44100: |
275 for (;c<size;c++) { | 260 soundFormat |= 0x0C; |
276 flv->audioFifo[(flv->audioOutPos+c)%AUDIO_FIFO_SIZE] = buf[c]; | 261 break; |
277 } | 262 case 22050: |
278 flv->audioSize += size; | 263 soundFormat |= 0x08; |
279 flv->audioOutPos += size; | 264 break; |
280 flv->audioOutPos %= AUDIO_FIFO_SIZE; | 265 case 11025: |
281 | 266 soundFormat |= 0x04; |
282 if ( flv->initDelay == -1 ) { | 267 break; |
283 flv->initDelay = timestamp; | 268 case 8000: //nellymoser only |
284 } | 269 case 5512: //not mp3 |
270 soundFormat |= 0x00; | |
271 break; | |
272 default: | |
273 assert(0); | |
274 } | |
275 | |
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; | |
285 | 298 |
286 // if ( flv->audioTime == -1 ) { | 299 // if ( flv->audioTime == -1 ) { |
287 flv->audioTime = timestamp; | |
288 // flv->audioTime = ( ( ( flv->sampleCount - enc->delay ) * 8000 ) / flv->audioRate ) - flv->initDelay - 250; | 300 // flv->audioTime = ( ( ( flv->sampleCount - enc->delay ) * 8000 ) / flv->audioRate ) - flv->initDelay - 250; |
289 // if ( flv->audioTime < 0 ) { | 301 // if ( flv->audioTime < 0 ) { |
290 // flv->audioTime = 0; | 302 // flv->audioTime = 0; |
291 // } | 303 // } |
292 // } | 304 // } |
293 } | 305 |
294 for ( ; flv->audioSize >= 4 ; ) { | 306 #ifdef CONFIG_MP3LAME |
295 | 307 if (enc->codec_id == CODEC_ID_MP3 ) { |
296 int mp3FrameSize = 0; | 308 int mp3FrameSize = 0; |
297 int mp3SampleRate = 0; | 309 int mp3SampleRate = 0; |
298 int mp3IsMono = 0; | 310 int mp3IsMono = 0; |
299 int mp3SamplesPerFrame = 0; | 311 int mp3SamplesPerFrame = 0; |
300 int c=0; | |
301 | 312 |
302 /* copy out mp3 header from ring buffer */ | 313 /* copy out mp3 header from ring buffer */ |
303 uint8_t header[4]; | 314 if(!mp3info(buf,&mp3FrameSize,&mp3SamplesPerFrame,&mp3SampleRate,&mp3IsMono)) |
304 for (c=0; c<4; c++) { | 315 assert(0); |
305 header[c] = flv->audioFifo[(flv->audioInPos+c) % AUDIO_FIFO_SIZE]; | 316 assert ( size == mp3FrameSize ); |
306 } | 317 assert(enc->sample_rate == mp3SampleRate); |
307 | 318 // assert(enc->frame_size == mp3SamplesPerFrame); |
308 if ( mp3info(header,&mp3FrameSize,&mp3SamplesPerFrame,&mp3SampleRate,&mp3IsMono) ) { | 319 //av_log(NULL, AV_LOG_DEBUG, "sizes: %d %d\n", enc->frame_size, mp3SamplesPerFrame); |
309 if ( flv->audioSize >= mp3FrameSize ) { | 320 |
310 | 321 frame->timestamp = (1000*flv->sampleCount + enc->sample_rate/2)/(enc->sample_rate); |
311 int soundFormat = 0x22; | 322 flv->sampleCount += mp3SamplesPerFrame; |
312 int c=0; | |
313 FLVFrame *frame = av_malloc(sizeof(FLVFrame)); | |
314 | |
315 // flv->audioRate = mp3SampleRate; | |
316 | |
317 switch (mp3SampleRate) { | |
318 case 44100: | |
319 soundFormat |= 0x0C; | |
320 break; | |
321 case 22050: | |
322 soundFormat |= 0x08; | |
323 break; | |
324 case 11025: | |
325 soundFormat |= 0x04; | |
326 break; | |
327 } | |
328 | |
329 if ( !mp3IsMono ) { | |
330 soundFormat |= 0x01; | |
331 } | |
332 | |
333 frame->next = 0; | |
334 frame->type = 8; | |
335 frame->flags = soundFormat; | |
336 frame->timestamp = flv->audioTime; | |
337 frame->timestamp = (1000*flv->sampleCount + mp3SampleRate/2)/(mp3SampleRate); | |
338 frame->size = mp3FrameSize; | |
339 frame->data = av_malloc(mp3FrameSize); | |
340 | |
341 for (;c<mp3FrameSize;c++) { | |
342 frame->data[c] = flv->audioFifo[(flv->audioInPos+c)%AUDIO_FIFO_SIZE]; | |
343 } | |
344 | |
345 flv->audioInPos += mp3FrameSize; | |
346 flv->audioSize -= mp3FrameSize; | |
347 flv->audioInPos %= AUDIO_FIFO_SIZE; | |
348 flv->sampleCount += mp3SamplesPerFrame; | |
349 | |
350 flv->audioTime += 1000*mp3SamplesPerFrame/mp3SampleRate; | |
351 // We got audio! Make sure we set this to the global flags on closure | |
352 flv->hasAudio = 1; | |
353 | |
354 InsertSorted(flv,frame); | |
355 // av_log(NULL,AV_LOG_DEBUG, "insert sound\n"); | |
356 continue; | |
357 } | |
358 // av_log(NULL,AV_LOG_DEBUG, "insuficent data\n"); | |
359 break; | |
360 } | |
361 av_log(NULL,AV_LOG_DEBUG, "head trashed\n"); | |
362 flv->audioInPos ++; | |
363 flv->audioSize --; | |
364 flv->audioInPos %= AUDIO_FIFO_SIZE; | |
365 // no audio in here! | |
366 flv->audioTime = -1; | |
367 } | 323 } |
368 #endif | 324 #endif |
369 } | 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); | |
370 Dump(flv,pb,128); | 331 Dump(flv,pb,128); |
371 put_flush_packet(pb); | 332 put_flush_packet(pb); |
372 return 0; | 333 return 0; |
373 } | 334 } |
374 | 335 |