Commit | Line | Data |
---|---|---|
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 | |
5509bffa | 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
d4f5d74a GM |
18 | */ |
19 | #include "avformat.h" | |
20 | ||
068f2a22 MN |
21 | #undef NDEBUG |
22 | #include <assert.h> | |
23 | ||
d4f5d74a GM |
24 | typedef struct FLVContext { |
25 | int hasAudio; | |
26 | int hasVideo; | |
11a8e425 | 27 | int reserved; |
d4f5d74a GM |
28 | } FLVContext; |
29 | ||
37cdf93d | 30 | static int get_audio_flags(AVCodecContext *enc){ |
2f5132e7 | 31 | int flags = (enc->bits_per_sample == 16) ? 0x2 : 0x0; |
37cdf93d MN |
32 | |
33 | switch (enc->sample_rate) { | |
34 | case 44100: | |
35 | flags |= 0x0C; | |
36 | break; | |
37 | case 22050: | |
38 | flags |= 0x08; | |
39 | break; | |
40 | case 11025: | |
41 | flags |= 0x04; | |
42 | break; | |
43 | case 8000: //nellymoser only | |
44 | case 5512: //not mp3 | |
45 | flags |= 0x00; | |
46 | break; | |
47 | default: | |
a254c574 | 48 | av_log(enc, AV_LOG_ERROR, "flv doesnt support that sample rate, choose from (44100, 22050, 11025)\n"); |
37cdf93d MN |
49 | return -1; |
50 | } | |
51 | ||
52 | if (enc->channels > 1) { | |
53 | flags |= 0x01; | |
54 | } | |
115329f1 | 55 | |
37cdf93d MN |
56 | switch(enc->codec_id){ |
57 | case CODEC_ID_MP3: | |
923bd441 | 58 | flags |= 0x20 | 0x2; |
37cdf93d | 59 | break; |
923bd441 | 60 | case CODEC_ID_PCM_S8: |
bb270c08 | 61 | break; |
923bd441 | 62 | case CODEC_ID_PCM_S16BE: |
bb270c08 DB |
63 | flags |= 0x60 | 0x2; |
64 | break; | |
923bd441 | 65 | case CODEC_ID_PCM_S16LE: |
bb270c08 DB |
66 | flags |= 0x2; |
67 | break; | |
2fde8aae | 68 | case CODEC_ID_ADPCM_SWF: |
bb270c08 DB |
69 | flags |= 0x10; |
70 | break; | |
37cdf93d MN |
71 | case 0: |
72 | flags |= enc->codec_tag<<4; | |
73 | break; | |
74 | default: | |
a254c574 | 75 | av_log(enc, AV_LOG_ERROR, "codec not compatible with flv\n"); |
37cdf93d MN |
76 | return -1; |
77 | } | |
115329f1 | 78 | |
37cdf93d MN |
79 | return flags; |
80 | } | |
81 | ||
d4f5d74a GM |
82 | static int flv_write_header(AVFormatContext *s) |
83 | { | |
84 | ByteIOContext *pb = &s->pb; | |
85 | FLVContext *flv = s->priv_data; | |
11a8e425 | 86 | int i; |
d4f5d74a | 87 | |
d4f5d74a GM |
88 | flv->hasAudio = 0; |
89 | flv->hasVideo = 0; | |
90 | ||
d4f5d74a GM |
91 | put_tag(pb,"FLV"); |
92 | put_byte(pb,1); | |
93 | put_byte(pb,0); // delayed write | |
94 | put_be32(pb,9); | |
95 | put_be32(pb,0); | |
115329f1 | 96 | |
11a8e425 | 97 | for(i=0; i<s->nb_streams; i++){ |
01f4895c | 98 | AVCodecContext *enc = s->streams[i]->codec; |
9ee91c2f | 99 | av_set_pts_info(s->streams[i], 24, 1, 1000); /* 24 bit pts in ms */ |
11a8e425 MN |
100 | if(enc->codec_tag == 5){ |
101 | put_byte(pb,8); // message type | |
102 | put_be24(pb,0); // include flags | |
103 | put_be24(pb,0); // time stamp | |
104 | put_be32(pb,0); // reserved | |
105 | put_be32(pb,11); // size | |
106 | flv->reserved=5; | |
107 | } | |
37cdf93d MN |
108 | if(enc->codec_type == CODEC_TYPE_AUDIO && get_audio_flags(enc)<0) |
109 | return -1; | |
11a8e425 | 110 | } |
d4f5d74a GM |
111 | |
112 | return 0; | |
113 | } | |
114 | ||
d4f5d74a GM |
115 | static int flv_write_trailer(AVFormatContext *s) |
116 | { | |
14b32253 MN |
117 | int64_t file_size; |
118 | int flags = 0; | |
119 | ||
d4f5d74a GM |
120 | ByteIOContext *pb = &s->pb; |
121 | FLVContext *flv = s->priv_data; | |
122 | ||
14b32253 | 123 | file_size = url_ftell(pb); |
d4f5d74a GM |
124 | flags |= flv->hasAudio ? 4 : 0; |
125 | flags |= flv->hasVideo ? 1 : 0; | |
126 | url_fseek(pb, 4, SEEK_SET); | |
127 | put_byte(pb,flags); | |
128 | url_fseek(pb, file_size, SEEK_SET); | |
129 | return 0; | |
130 | } | |
131 | ||
e928649b | 132 | static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) |
d4f5d74a GM |
133 | { |
134 | ByteIOContext *pb = &s->pb; | |
01f4895c | 135 | AVCodecContext *enc = s->streams[pkt->stream_index]->codec; |
d4f5d74a | 136 | FLVContext *flv = s->priv_data; |
e928649b | 137 | int size= pkt->size; |
75293f05 | 138 | int flags; |
d4f5d74a | 139 | |
068f2a22 | 140 | // av_log(s, AV_LOG_DEBUG, "type:%d pts: %lld size:%d\n", enc->codec_type, timestamp, size); |
115329f1 | 141 | |
d4f5d74a | 142 | if (enc->codec_type == CODEC_TYPE_VIDEO) { |
75293f05 MN |
143 | put_byte(pb, 9); |
144 | flags = 2; // choose h263 | |
145 | flags |= pkt->flags & PKT_FLAG_KEY ? 0x10 : 0x20; // add keyframe indicator | |
d4f5d74a | 146 | flv->hasVideo = 1; |
75293f05 MN |
147 | } else { |
148 | assert(enc->codec_type == CODEC_TYPE_AUDIO); | |
37cdf93d | 149 | flags = get_audio_flags(enc); |
115329f1 | 150 | |
068f2a22 | 151 | assert(size); |
068f2a22 | 152 | |
75293f05 | 153 | put_byte(pb, 8); |
068f2a22 MN |
154 | |
155 | // We got audio! Make sure we set this to the global flags on closure | |
156 | flv->hasAudio = 1; | |
75293f05 MN |
157 | } |
158 | ||
159 | put_be24(pb,size+1); // include flags | |
160 | put_be24(pb,pkt->pts); | |
161 | put_be32(pb,flv->reserved); | |
162 | put_byte(pb,flags); | |
163 | put_buffer(pb, pkt->data, size); | |
923bd441 | 164 | put_be32(pb,size+1+11); // previous tag size |
115329f1 | 165 | |
d4f5d74a GM |
166 | put_flush_packet(pb); |
167 | return 0; | |
168 | } | |
169 | ||
ff70e601 | 170 | AVOutputFormat flv_muxer = { |
d4f5d74a GM |
171 | "flv", |
172 | "flv format", | |
e817a73d | 173 | "video/x-flv", |
d4f5d74a GM |
174 | "flv", |
175 | sizeof(FLVContext), | |
176 | #ifdef CONFIG_MP3LAME | |
80783dc2 | 177 | CODEC_ID_MP3, |
d4f5d74a GM |
178 | #else // CONFIG_MP3LAME |
179 | CODEC_ID_NONE, | |
180 | #endif // CONFIG_MP3LAME | |
181 | CODEC_ID_FLV1, | |
182 | flv_write_header, | |
183 | flv_write_packet, | |
184 | flv_write_trailer, | |
185 | }; |