├── LICENSE
├── README.md
├── flv.h
├── flvdec.c
└── flvenc.c
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Alex.CR
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 在ffmpeg中支持hevc/vp8/vp9/opus的flv格式
2 | ## 项目背景
3 | 1. 当前阿里云,金山云等众多cdn,已经支持hevc in rtmp/flv(采用增加codecid=12的方式)
4 | 2. 国外大厂和国外cdn支持hevc in rtmp/flv方式:[enhanced-rtmp](https://github.com/veovera/enhanced-rtmp)
5 |
6 | 基于兼容上面两种hevc in rtmp/flv的方式,本库均支持。
7 |
8 | ## 本库支持的版本(见对应的branch分支):
9 | * 4.1
10 | * 4.3
11 | * 5.0
12 | * 5.1
13 | * 6.0(支持enhanced-rtmp)
14 |
15 | ## 国内cdn方式: 新增codecid
16 | hevc/vp8/vp9/opus在rtmp中的codecid没有官方协议定义,由国内众多知名cdn共同制定。
17 |
18 |
19 | FLV_CODECID_OPUS = 9 << FLV_AUDIO_CODECID_OFFSET
20 |
21 | enum {
22 | FLV_CODECID_H263 = 2,
23 | FLV_CODECID_SCREEN = 3,
24 | FLV_CODECID_VP6 = 4,
25 | FLV_CODECID_VP6A = 5,
26 | FLV_CODECID_SCREEN2 = 6,
27 | FLV_CODECID_H264 = 7,
28 | FLV_CODECID_REALH263= 8,
29 | FLV_CODECID_MPEG4 = 9,
30 | FLV_CODECID_HEVC = 12,
31 | FLV_CODECID_AV1 = 13,
32 | FLV_CODECID_VP8 = 14,
33 | FLV_CODECID_VP9 = 15,
34 | };
35 |
36 |
37 |
38 | ## 国外大厂和cdn方式:[enhanced-rtmp](https://github.com/veovera/enhanced-rtmp)
39 | * mux/推流:需要设置: -f flv -flvflags ext_header
40 | ```markup
41 | ffmpeg -re -i source.flv -c:v libx265 -c:a copy -f flv -flvflags ext_header rtmp://192.168.0.1/live/1000
42 | ```
43 | * demux/拉流: 不需要格外操作,自动识别
44 |
45 | ## 编译
46 |
47 | 只需要把flv.h/flvdec.c/flvenc.c拷贝入libavformat文件夹中,后面ffmpeg正常编译即可。
48 |
49 |
50 |
--------------------------------------------------------------------------------
/flv.h:
--------------------------------------------------------------------------------
1 | /*
2 | FLV common header
3 | *
4 | * Copyright (c) 2006 The FFmpeg Project
5 | *
6 | * This file is part of FFmpeg.
7 | *
8 | * FFmpeg is free software; you can redistribute it and/or
9 | * modify it under the terms of the GNU Lesser General Public
10 | * License as published by the Free Software Foundation; either
11 | * version 2.1 of the License, or (at your option) any later version.
12 | *
13 | * FFmpeg 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 GNU
16 | * Lesser General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU Lesser General Public
19 | * License along with FFmpeg; if not, write to the Free Software
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 | */
22 |
23 | /*
24 | *@file
25 | *FLV common header
26 | */
27 |
28 | #ifndef AVFORMAT_FLV_H
29 | #define AVFORMAT_FLV_H
30 |
31 | /* offsets for packed values */
32 | #define FLV_AUDIO_SAMPLESSIZE_OFFSET 1
33 | #define FLV_AUDIO_SAMPLERATE_OFFSET 2
34 | #define FLV_AUDIO_CODECID_OFFSET 4
35 |
36 | #define FLV_VIDEO_FRAMETYPE_OFFSET 4
37 | #define FRAME_HEADER_EX (8 << FLV_VIDEO_FRAMETYPE_OFFSET)
38 |
39 | enum video_frametype_t {
40 | FT_KEY = 1 << FLV_VIDEO_FRAMETYPE_OFFSET,
41 | FT_INTER = 2 << FLV_VIDEO_FRAMETYPE_OFFSET,
42 | };
43 |
44 | enum packet_type_t {
45 | PACKETTYPE_SEQ_START = 0,
46 | PACKETTYPE_FRAMES = 1,
47 | PACKETTYPE_SEQ_END = 2,
48 | PACKETTYPE_FRAMESX = 3,
49 | PACKETTYPE_METADATA = 4
50 | };
51 |
52 | /* bitmasks to isolate specific values */
53 | #define FLV_AUDIO_CHANNEL_MASK 0x01
54 | #define FLV_AUDIO_SAMPLESIZE_MASK 0x02
55 | #define FLV_AUDIO_SAMPLERATE_MASK 0x0c
56 | #define FLV_AUDIO_CODECID_MASK 0xf0
57 |
58 | #define FLV_VIDEO_CODECID_MASK 0x0f
59 | #define FLV_VIDEO_FRAMETYPE_MASK 0xf0
60 |
61 | #define AMF_END_OF_OBJECT 0x09
62 |
63 | #define KEYFRAMES_TAG "keyframes"
64 | #define KEYFRAMES_TIMESTAMP_TAG "times"
65 | #define KEYFRAMES_BYTEOFFSET_TAG "filepositions"
66 |
67 | #define IS_EXT_HEADER(x) (((x) & FRAME_HEADER_EX) == FRAME_HEADER_EX)
68 | #define GET_PACKET_TYPE(x) ((x) & FLV_VIDEO_CODECID_MASK)
69 | #define EXT_HEADER_IS_SEQFRAME(x) (((x) & FLV_VIDEO_CODECID_MASK) == PACKETTYPE_SEQ_START)
70 | #define EXT_HEADER_IS_FRAMES(x) (((x) & FLV_VIDEO_CODECID_MASK) == PACKETTYPE_FRAMES)
71 | #define EXT_HEADER_IS_FRAMESX(x) (((x) & FLV_VIDEO_CODECID_MASK) == PACKETTYPE_FRAMESX)
72 | #define EXT_HEADER_IS_ENDFRAME(x) (((x) & FLV_VIDEO_CODECID_MASK) == PACKETTYPE_SEQ_END)
73 |
74 | #define EXT_HEADER_IS_KEYFRAME(x) (((x) & FLV_VIDEO_FRAMETYPE_MASK) == FT_KEY)
75 | #define EXT_HEADER_IS_INTERFRAME(x) (((x) & FLV_VIDEO_FRAMETYPE_MASK) == FT_INTER)
76 |
77 |
78 | enum {
79 | FLV_HEADER_FLAG_HASVIDEO = 1,
80 | FLV_HEADER_FLAG_HASAUDIO = 4,
81 | };
82 |
83 | enum FlvTagType {
84 | FLV_TAG_TYPE_AUDIO = 0x08,
85 | FLV_TAG_TYPE_VIDEO = 0x09,
86 | FLV_TAG_TYPE_META = 0x12,
87 | };
88 |
89 | enum {
90 | FLV_STREAM_TYPE_VIDEO,
91 | FLV_STREAM_TYPE_AUDIO,
92 | FLV_STREAM_TYPE_SUBTITLE,
93 | FLV_STREAM_TYPE_DATA,
94 | FLV_STREAM_TYPE_NB,
95 | };
96 |
97 | enum {
98 | FLV_MONO = 0,
99 | FLV_STEREO = 1,
100 | };
101 |
102 | enum {
103 | FLV_SAMPLESSIZE_8BIT = 0,
104 | FLV_SAMPLESSIZE_16BIT = 1 << FLV_AUDIO_SAMPLESSIZE_OFFSET,
105 | };
106 |
107 | enum {
108 | FLV_SAMPLERATE_SPECIAL = 0, /**< signifies 5512Hz and 8000Hz in the case of NELLYMOSER */
109 | FLV_SAMPLERATE_11025HZ = 1 << FLV_AUDIO_SAMPLERATE_OFFSET,
110 | FLV_SAMPLERATE_22050HZ = 2 << FLV_AUDIO_SAMPLERATE_OFFSET,
111 | FLV_SAMPLERATE_44100HZ = 3 << FLV_AUDIO_SAMPLERATE_OFFSET,
112 | };
113 |
114 | enum {
115 | FLV_CODECID_PCM = 0,
116 | FLV_CODECID_ADPCM = 1 << FLV_AUDIO_CODECID_OFFSET,
117 | FLV_CODECID_MP3 = 2 << FLV_AUDIO_CODECID_OFFSET,
118 | FLV_CODECID_PCM_LE = 3 << FLV_AUDIO_CODECID_OFFSET,
119 | FLV_CODECID_NELLYMOSER_16KHZ_MONO = 4 << FLV_AUDIO_CODECID_OFFSET,
120 | FLV_CODECID_NELLYMOSER_8KHZ_MONO = 5 << FLV_AUDIO_CODECID_OFFSET,
121 | FLV_CODECID_NELLYMOSER = 6 << FLV_AUDIO_CODECID_OFFSET,
122 | FLV_CODECID_PCM_ALAW = 7 << FLV_AUDIO_CODECID_OFFSET,
123 | FLV_CODECID_PCM_MULAW = 8 << FLV_AUDIO_CODECID_OFFSET,
124 | FLV_CODECID_OPUS = 9 << FLV_AUDIO_CODECID_OFFSET,
125 | FLV_CODECID_AAC = 10<< FLV_AUDIO_CODECID_OFFSET,
126 | FLV_CODECID_SPEEX = 11<< FLV_AUDIO_CODECID_OFFSET,
127 | };
128 |
129 | enum {
130 | FLV_CODECID_H263 = 2,
131 | FLV_CODECID_SCREEN = 3,
132 | FLV_CODECID_VP6 = 4,
133 | FLV_CODECID_VP6A = 5,
134 | FLV_CODECID_SCREEN2 = 6,
135 | FLV_CODECID_H264 = 7,
136 | FLV_CODECID_REALH263= 8,
137 | FLV_CODECID_MPEG4 = 9,
138 | FLV_CODECID_HEVC = 12,
139 | FLV_CODECID_AV1 = 13,
140 | FLV_CODECID_VP8 = 14,
141 | FLV_CODECID_VP9 = 15,
142 | };
143 |
144 | enum {
145 | FLV_FRAME_KEY = 1 << FLV_VIDEO_FRAMETYPE_OFFSET, ///< key frame (for AVC, a seekable frame)
146 | FLV_FRAME_INTER = 2 << FLV_VIDEO_FRAMETYPE_OFFSET, ///< inter frame (for AVC, a non-seekable frame)
147 | FLV_FRAME_DISP_INTER = 3 << FLV_VIDEO_FRAMETYPE_OFFSET, ///< disposable inter frame (H.263 only)
148 | FLV_FRAME_GENERATED_KEY = 4 << FLV_VIDEO_FRAMETYPE_OFFSET, ///< generated key frame (reserved for server use only)
149 | FLV_FRAME_VIDEO_INFO_CMD = 5 << FLV_VIDEO_FRAMETYPE_OFFSET, ///< video info/command frame
150 | };
151 |
152 | typedef enum {
153 | AMF_DATA_TYPE_NUMBER = 0x00,
154 | AMF_DATA_TYPE_BOOL = 0x01,
155 | AMF_DATA_TYPE_STRING = 0x02,
156 | AMF_DATA_TYPE_OBJECT = 0x03,
157 | AMF_DATA_TYPE_NULL = 0x05,
158 | AMF_DATA_TYPE_UNDEFINED = 0x06,
159 | AMF_DATA_TYPE_REFERENCE = 0x07,
160 | AMF_DATA_TYPE_MIXEDARRAY = 0x08,
161 | AMF_DATA_TYPE_OBJECT_END = 0x09,
162 | AMF_DATA_TYPE_ARRAY = 0x0a,
163 | AMF_DATA_TYPE_DATE = 0x0b,
164 | AMF_DATA_TYPE_LONG_STRING = 0x0c,
165 | AMF_DATA_TYPE_UNSUPPORTED = 0x0d,
166 | } AMFDataType;
167 |
168 | #endif /* AVFORMAT_FLV_H */
169 |
--------------------------------------------------------------------------------
/flvdec.c:
--------------------------------------------------------------------------------
1 | /*
2 | * FLV demuxer
3 | * Copyright (c) 2003 The FFmpeg Project
4 | *
5 | * This demuxer will generate a 1 byte extradata for VP6F content.
6 | * It is composed of:
7 | * - upper 4 bits: difference between encoded width and visible width
8 | * - lower 4 bits: difference between encoded height and visible height
9 | *
10 | * This file is part of FFmpeg.
11 | *
12 | * FFmpeg is free software; you can redistribute it and/or
13 | * modify it under the terms of the GNU Lesser General Public
14 | * License as published by the Free Software Foundation; either
15 | * version 2.1 of the License, or (at your option) any later version.
16 | *
17 | * FFmpeg is distributed in the hope that it will be useful,
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 | * Lesser General Public License for more details.
21 | *
22 | * You should have received a copy of the GNU Lesser General Public
23 | * License along with FFmpeg; if not, write to the Free Software
24 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 | */
26 |
27 | #include "libavutil/avassert.h"
28 | #include "libavutil/avstring.h"
29 | #include "libavutil/channel_layout.h"
30 | #include "libavutil/dict.h"
31 | #include "libavutil/dict_internal.h"
32 | #include "libavutil/opt.h"
33 | #include "libavutil/internal.h"
34 | #include "libavutil/intfloat.h"
35 | #include "libavutil/intreadwrite.h"
36 | #include "libavutil/mathematics.h"
37 | #include "avformat.h"
38 | #include "demux.h"
39 | #include "internal.h"
40 | #include "flv.h"
41 |
42 | #define VALIDATE_INDEX_TS_THRESH 2500
43 |
44 | #define RESYNC_BUFFER_SIZE (1<<20)
45 |
46 | #define MAX_DEPTH 16 ///< arbitrary limit to prevent unbounded recursion
47 |
48 | typedef struct FLVContext {
49 | const AVClass *class; ///< Class for private options.
50 | int trust_metadata; ///< configure streams according onMetaData
51 | int trust_datasize; ///< trust data size of FLVTag
52 | int dump_full_metadata; ///< Dump full metadata of the onMetadata
53 | int wrong_dts; ///< wrong dts due to negative cts
54 | uint8_t *new_extradata[FLV_STREAM_TYPE_NB];
55 | int new_extradata_size[FLV_STREAM_TYPE_NB];
56 | int last_sample_rate;
57 | int last_channels;
58 | struct {
59 | int64_t dts;
60 | int64_t pos;
61 | } validate_index[2];
62 | int validate_next;
63 | int validate_count;
64 | int searched_for_end;
65 |
66 | uint8_t resync_buffer[2*RESYNC_BUFFER_SIZE];
67 |
68 | int broken_sizes;
69 | int64_t sum_flv_tag_size;
70 |
71 | int last_keyframe_stream_index;
72 | int keyframe_count;
73 | int64_t video_bit_rate;
74 | int64_t audio_bit_rate;
75 | int64_t *keyframe_times;
76 | int64_t *keyframe_filepositions;
77 | int missing_streams;
78 | AVRational framerate;
79 | int64_t last_ts;
80 | int64_t time_offset;
81 | int64_t time_pos;
82 | } FLVContext;
83 |
84 | /* AMF date type */
85 | typedef struct amf_date {
86 | double milliseconds;
87 | int16_t timezone;
88 | } amf_date;
89 |
90 | static int probe(const AVProbeData *p, int live)
91 | {
92 | const uint8_t *d = p->buf;
93 | unsigned offset = AV_RB32(d + 5);
94 |
95 | if (d[0] == 'F' &&
96 | d[1] == 'L' &&
97 | d[2] == 'V' &&
98 | d[3] < 5 && d[5] == 0 &&
99 | offset + 100 < p->buf_size &&
100 | offset > 8) {
101 | int is_live = !memcmp(d + offset + 40, "NGINX RTMP", 10);
102 |
103 | if (live == is_live)
104 | return AVPROBE_SCORE_MAX;
105 | }
106 | return 0;
107 | }
108 |
109 | static int flv_probe(const AVProbeData *p)
110 | {
111 | return probe(p, 0);
112 | }
113 |
114 | static int live_flv_probe(const AVProbeData *p)
115 | {
116 | return probe(p, 1);
117 | }
118 |
119 | static int kux_probe(const AVProbeData *p)
120 | {
121 | const uint8_t *d = p->buf;
122 |
123 | if (d[0] == 'K' &&
124 | d[1] == 'D' &&
125 | d[2] == 'K' &&
126 | d[3] == 0 &&
127 | d[4] == 0) {
128 | return AVPROBE_SCORE_EXTENSION + 1;
129 | }
130 | return 0;
131 | }
132 |
133 | static void add_keyframes_index(AVFormatContext *s)
134 | {
135 | FLVContext *flv = s->priv_data;
136 | AVStream *stream = NULL;
137 | unsigned int i = 0;
138 |
139 | if (flv->last_keyframe_stream_index < 0) {
140 | av_log(s, AV_LOG_DEBUG, "keyframe stream hasn't been created\n");
141 | return;
142 | }
143 |
144 | av_assert0(flv->last_keyframe_stream_index <= s->nb_streams);
145 | stream = s->streams[flv->last_keyframe_stream_index];
146 |
147 | if (ffstream(stream)->nb_index_entries == 0) {
148 | for (i = 0; i < flv->keyframe_count; i++) {
149 | av_log(s, AV_LOG_TRACE, "keyframe filepositions = %"PRId64" times = %"PRId64"\n",
150 | flv->keyframe_filepositions[i], flv->keyframe_times[i]);
151 | av_add_index_entry(stream, flv->keyframe_filepositions[i],
152 | flv->keyframe_times[i], 0, 0, AVINDEX_KEYFRAME);
153 | }
154 | } else
155 | av_log(s, AV_LOG_WARNING, "Skipping duplicate index\n");
156 |
157 | if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
158 | av_freep(&flv->keyframe_times);
159 | av_freep(&flv->keyframe_filepositions);
160 | flv->keyframe_count = 0;
161 | }
162 | }
163 |
164 | static AVStream *create_stream(AVFormatContext *s, int codec_type)
165 | {
166 | FLVContext *flv = s->priv_data;
167 | AVStream *st = avformat_new_stream(s, NULL);
168 | if (!st)
169 | return NULL;
170 | st->codecpar->codec_type = codec_type;
171 | if (s->nb_streams>=3 ||( s->nb_streams==2
172 | && s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE
173 | && s->streams[1]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE
174 | && s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_DATA
175 | && s->streams[1]->codecpar->codec_type != AVMEDIA_TYPE_DATA))
176 | s->ctx_flags &= ~AVFMTCTX_NOHEADER;
177 | if (codec_type == AVMEDIA_TYPE_AUDIO) {
178 | st->codecpar->bit_rate = flv->audio_bit_rate;
179 | flv->missing_streams &= ~FLV_HEADER_FLAG_HASAUDIO;
180 | }
181 | if (codec_type == AVMEDIA_TYPE_VIDEO) {
182 | st->codecpar->bit_rate = flv->video_bit_rate;
183 | flv->missing_streams &= ~FLV_HEADER_FLAG_HASVIDEO;
184 | st->avg_frame_rate = flv->framerate;
185 | }
186 |
187 |
188 | avpriv_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */
189 | flv->last_keyframe_stream_index = s->nb_streams - 1;
190 | add_keyframes_index(s);
191 | return st;
192 | }
193 |
194 | static int flv_same_audio_codec(AVCodecParameters *apar, int flags)
195 | {
196 | int bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8;
197 | int flv_codecid = flags & FLV_AUDIO_CODECID_MASK;
198 | int codec_id;
199 |
200 | if (!apar->codec_id && !apar->codec_tag)
201 | return 1;
202 |
203 | if (apar->bits_per_coded_sample != bits_per_coded_sample)
204 | return 0;
205 |
206 | switch (flv_codecid) {
207 | // no distinction between S16 and S8 PCM codec flags
208 | case FLV_CODECID_PCM:
209 | codec_id = bits_per_coded_sample == 8
210 | ? AV_CODEC_ID_PCM_U8
211 | #if HAVE_BIGENDIAN
212 | : AV_CODEC_ID_PCM_S16BE;
213 | #else
214 | : AV_CODEC_ID_PCM_S16LE;
215 | #endif
216 | return codec_id == apar->codec_id;
217 | case FLV_CODECID_PCM_LE:
218 | codec_id = bits_per_coded_sample == 8
219 | ? AV_CODEC_ID_PCM_U8
220 | : AV_CODEC_ID_PCM_S16LE;
221 | return codec_id == apar->codec_id;
222 | case FLV_CODECID_AAC:
223 | return apar->codec_id == AV_CODEC_ID_AAC;
224 | case FLV_CODECID_ADPCM:
225 | return apar->codec_id == AV_CODEC_ID_ADPCM_SWF;
226 | case FLV_CODECID_SPEEX:
227 | return apar->codec_id == AV_CODEC_ID_SPEEX;
228 | case FLV_CODECID_MP3:
229 | return apar->codec_id == AV_CODEC_ID_MP3;
230 | case FLV_CODECID_NELLYMOSER_8KHZ_MONO:
231 | case FLV_CODECID_NELLYMOSER_16KHZ_MONO:
232 | case FLV_CODECID_NELLYMOSER:
233 | return apar->codec_id == AV_CODEC_ID_NELLYMOSER;
234 | case FLV_CODECID_PCM_MULAW:
235 | return apar->sample_rate == 8000 &&
236 | apar->codec_id == AV_CODEC_ID_PCM_MULAW;
237 | case FLV_CODECID_PCM_ALAW:
238 | return apar->sample_rate == 8000 &&
239 | apar->codec_id == AV_CODEC_ID_PCM_ALAW;
240 | case FLV_CODECID_OPUS:
241 | return apar->codec_id == AV_CODEC_ID_OPUS;
242 | default:
243 | return apar->codec_tag == (flv_codecid >> FLV_AUDIO_CODECID_OFFSET);
244 | }
245 | }
246 |
247 | static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream,
248 | AVCodecParameters *apar, int flv_codecid)
249 | {
250 | switch (flv_codecid) {
251 | // no distinction between S16 and S8 PCM codec flags
252 | case FLV_CODECID_PCM:
253 | apar->codec_id = apar->bits_per_coded_sample == 8
254 | ? AV_CODEC_ID_PCM_U8
255 | #if HAVE_BIGENDIAN
256 | : AV_CODEC_ID_PCM_S16BE;
257 | #else
258 | : AV_CODEC_ID_PCM_S16LE;
259 | #endif
260 | break;
261 | case FLV_CODECID_PCM_LE:
262 | apar->codec_id = apar->bits_per_coded_sample == 8
263 | ? AV_CODEC_ID_PCM_U8
264 | : AV_CODEC_ID_PCM_S16LE;
265 | break;
266 | case FLV_CODECID_AAC:
267 | apar->codec_id = AV_CODEC_ID_AAC;
268 | break;
269 | case FLV_CODECID_ADPCM:
270 | apar->codec_id = AV_CODEC_ID_ADPCM_SWF;
271 | break;
272 | case FLV_CODECID_SPEEX:
273 | apar->codec_id = AV_CODEC_ID_SPEEX;
274 | apar->sample_rate = 16000;
275 | break;
276 | case FLV_CODECID_MP3:
277 | apar->codec_id = AV_CODEC_ID_MP3;
278 | ffstream(astream)->need_parsing = AVSTREAM_PARSE_FULL;
279 | break;
280 | case FLV_CODECID_NELLYMOSER_8KHZ_MONO:
281 | // in case metadata does not otherwise declare samplerate
282 | apar->sample_rate = 8000;
283 | apar->codec_id = AV_CODEC_ID_NELLYMOSER;
284 | break;
285 | case FLV_CODECID_NELLYMOSER_16KHZ_MONO:
286 | apar->sample_rate = 16000;
287 | apar->codec_id = AV_CODEC_ID_NELLYMOSER;
288 | break;
289 | case FLV_CODECID_NELLYMOSER:
290 | apar->codec_id = AV_CODEC_ID_NELLYMOSER;
291 | break;
292 | case FLV_CODECID_PCM_MULAW:
293 | apar->sample_rate = 8000;
294 | apar->codec_id = AV_CODEC_ID_PCM_MULAW;
295 | break;
296 | case FLV_CODECID_PCM_ALAW:
297 | apar->sample_rate = 8000;
298 | apar->codec_id = AV_CODEC_ID_PCM_ALAW;
299 | break;
300 | case FLV_CODECID_OPUS:
301 | apar->codec_id = AV_CODEC_ID_OPUS;
302 | break;
303 | default:
304 | avpriv_request_sample(s, "Audio codec (%x)",
305 | flv_codecid >> FLV_AUDIO_CODECID_OFFSET);
306 | apar->codec_tag = flv_codecid >> FLV_AUDIO_CODECID_OFFSET;
307 | }
308 | }
309 |
310 | static void read_codec_fourcc(AVFormatContext* s, char* fourcc) {
311 | fourcc[0] = avio_r8(s->pb);
312 | fourcc[1] = avio_r8(s->pb);
313 | fourcc[2] = avio_r8(s->pb);
314 | fourcc[3] = avio_r8(s->pb);
315 | }
316 |
317 | static int is_av1_fourcc(char* fourcc) {
318 | return fourcc[0] == 'a' && fourcc[1] == 'v'
319 | && fourcc[2] == '0' && fourcc[3] == '1';
320 | }
321 |
322 | static int is_hevc_fourcc(char* fourcc) {
323 | return fourcc[0] == 'h' && fourcc[1] == 'v'
324 | && fourcc[2] == 'c' && fourcc[3] == '1';
325 | }
326 |
327 | static int flv_same_video_codec(AVFormatContext* s, AVCodecParameters *vpar, int flags)
328 | {
329 | int flv_codecid = flags & FLV_VIDEO_CODECID_MASK;
330 |
331 | if (!vpar->codec_id && !vpar->codec_tag)
332 | return 1;
333 |
334 | //check whether Extended VideoTagHeader
335 | if (IS_EXT_HEADER(flags)) {
336 | char* hb = (char*)s->pb->buf_ptr;
337 | char codec_fourcc[4];
338 |
339 | codec_fourcc[0] = hb[0];
340 | codec_fourcc[1] = hb[1];
341 | codec_fourcc[2] = hb[2];
342 | codec_fourcc[3] = hb[3];
343 |
344 | if (is_av1_fourcc(codec_fourcc)) {
345 | return vpar->codec_id == AV_CODEC_ID_AV1;
346 | } else if (is_hevc_fourcc(codec_fourcc)) {
347 | return vpar->codec_id == AV_CODEC_ID_HEVC;
348 | } else {
349 | return vpar->codec_tag == flv_codecid;
350 | }
351 | }
352 |
353 | switch (flv_codecid) {
354 | case FLV_CODECID_H263:
355 | return vpar->codec_id == AV_CODEC_ID_FLV1;
356 | case FLV_CODECID_SCREEN:
357 | return vpar->codec_id == AV_CODEC_ID_FLASHSV;
358 | case FLV_CODECID_SCREEN2:
359 | return vpar->codec_id == AV_CODEC_ID_FLASHSV2;
360 | case FLV_CODECID_VP6:
361 | return vpar->codec_id == AV_CODEC_ID_VP6F;
362 | case FLV_CODECID_VP6A:
363 | return vpar->codec_id == AV_CODEC_ID_VP6A;
364 | case FLV_CODECID_H264:
365 | return vpar->codec_id == AV_CODEC_ID_H264;
366 | case FLV_CODECID_HEVC:
367 | return vpar->codec_id == AV_CODEC_ID_HEVC;
368 | case FLV_CODECID_VP8:
369 | return vpar->codec_id == AV_CODEC_ID_VP8;
370 | case FLV_CODECID_VP9:
371 | return vpar->codec_id == AV_CODEC_ID_VP9;
372 | default:
373 | return vpar->codec_tag == flv_codecid;
374 | }
375 | }
376 |
377 | static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream,
378 | int flv_codecid, int read)
379 | {
380 | FFStream *const vstreami = ffstream(vstream);
381 | int ret = 0;
382 | AVCodecParameters *par = vstream->codecpar;
383 | enum AVCodecID old_codec_id = vstream->codecpar->codec_id;
384 |
385 | if (IS_EXT_HEADER(flv_codecid)) {
386 | char codec_fourcc[4];
387 | read_codec_fourcc(s, codec_fourcc);
388 |
389 | if (is_av1_fourcc(codec_fourcc)) {
390 | par->codec_id = AV_CODEC_ID_AV1;
391 | vstreami->need_parsing = AVSTREAM_PARSE_NONE;
392 | ret = 4; // not 4, reading packet type will consume one byte
393 | } else if (is_hevc_fourcc(codec_fourcc)) {
394 | par->codec_id = AV_CODEC_ID_HEVC;
395 | vstreami->need_parsing = AVSTREAM_PARSE_NONE;
396 | ret = 4; // not 4, reading packet type will consume one byte
397 | } else {
398 | avpriv_request_sample(s, "Video codec (%x)", flv_codecid);
399 | par->codec_tag = flv_codecid;
400 | }
401 |
402 | if (!vstreami->need_context_update && par->codec_id != old_codec_id) {
403 | avpriv_request_sample(s, "Changing the codec id midstream");
404 | return AVERROR_PATCHWELCOME;
405 | }
406 | return ret;
407 | }
408 |
409 | flv_codecid = flv_codecid & FLV_VIDEO_CODECID_MASK;
410 | switch (flv_codecid) {
411 | case FLV_CODECID_H263:
412 | par->codec_id = AV_CODEC_ID_FLV1;
413 | break;
414 | case FLV_CODECID_REALH263:
415 | par->codec_id = AV_CODEC_ID_H263;
416 | break; // Really mean it this time
417 | case FLV_CODECID_SCREEN:
418 | par->codec_id = AV_CODEC_ID_FLASHSV;
419 | break;
420 | case FLV_CODECID_SCREEN2:
421 | par->codec_id = AV_CODEC_ID_FLASHSV2;
422 | break;
423 | case FLV_CODECID_VP6:
424 | par->codec_id = AV_CODEC_ID_VP6F;
425 | case FLV_CODECID_VP6A:
426 | if (flv_codecid == FLV_CODECID_VP6A)
427 | par->codec_id = AV_CODEC_ID_VP6A;
428 | if (read) {
429 | if (par->extradata_size != 1) {
430 | ff_alloc_extradata(par, 1);
431 | }
432 | if (par->extradata)
433 | par->extradata[0] = avio_r8(s->pb);
434 | else
435 | avio_skip(s->pb, 1);
436 | }
437 | ret = 1; // 1 byte body size adjustment for flv_read_packet()
438 | break;
439 | case FLV_CODECID_H264:
440 | par->codec_id = AV_CODEC_ID_H264;
441 | vstreami->need_parsing = AVSTREAM_PARSE_HEADERS;
442 | ret = 3; // not 4, reading packet type will consume one byte
443 | break;
444 | case FLV_CODECID_MPEG4:
445 | par->codec_id = AV_CODEC_ID_MPEG4;
446 | ret = 3;
447 | break;
448 | case FLV_CODECID_HEVC:
449 | par->codec_id = AV_CODEC_ID_HEVC;
450 | vstreami->need_parsing = AVSTREAM_PARSE_NONE;
451 | ret = 3; // not 4, reading packet type will consume one byte
452 | break;
453 | case FLV_CODECID_VP8:
454 | par->codec_id = AV_CODEC_ID_VP8;
455 | vstreami->need_parsing = AVSTREAM_PARSE_NONE;
456 | ret = 3; // not 4, reading packet type will consume one byte
457 | break;
458 | case FLV_CODECID_VP9:
459 | par->codec_id = AV_CODEC_ID_VP9;
460 | vstreami->need_parsing = AVSTREAM_PARSE_NONE;
461 | ret = 3; // not 4, reading packet type will consume one byte
462 | break;
463 | default:
464 | avpriv_request_sample(s, "Video codec (%x)", flv_codecid);
465 | par->codec_tag = flv_codecid;
466 | }
467 |
468 | if (!vstreami->need_context_update && par->codec_id != old_codec_id) {
469 | avpriv_request_sample(s, "Changing the codec id midstream");
470 | return AVERROR_PATCHWELCOME;
471 | }
472 |
473 | return ret;
474 | }
475 |
476 | static int amf_get_string(AVIOContext *ioc, char *buffer, int buffsize)
477 | {
478 | int ret;
479 | int length = avio_rb16(ioc);
480 | if (length >= buffsize) {
481 | avio_skip(ioc, length);
482 | return -1;
483 | }
484 |
485 | ret = avio_read(ioc, buffer, length);
486 | if (ret < 0)
487 | return ret;
488 | if (ret < length)
489 | return AVERROR_INVALIDDATA;
490 |
491 | buffer[length] = '\0';
492 |
493 | return length;
494 | }
495 |
496 | static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, int64_t max_pos)
497 | {
498 | FLVContext *flv = s->priv_data;
499 | unsigned int timeslen = 0, fileposlen = 0, i;
500 | char str_val[256];
501 | int64_t *times = NULL;
502 | int64_t *filepositions = NULL;
503 | int ret = AVERROR(ENOSYS);
504 | int64_t initial_pos = avio_tell(ioc);
505 |
506 | if (flv->keyframe_count > 0) {
507 | av_log(s, AV_LOG_DEBUG, "keyframes have been parsed\n");
508 | return 0;
509 | }
510 | av_assert0(!flv->keyframe_times);
511 | av_assert0(!flv->keyframe_filepositions);
512 |
513 | if (s->flags & AVFMT_FLAG_IGNIDX)
514 | return 0;
515 |
516 | while (avio_tell(ioc) < max_pos - 2 &&
517 | amf_get_string(ioc, str_val, sizeof(str_val)) > 0) {
518 | int64_t **current_array;
519 | unsigned int arraylen;
520 | int factor;
521 |
522 | // Expect array object in context
523 | if (avio_r8(ioc) != AMF_DATA_TYPE_ARRAY)
524 | break;
525 |
526 | arraylen = avio_rb32(ioc);
527 | if (arraylen>>28)
528 | break;
529 |
530 | if (!strcmp(KEYFRAMES_TIMESTAMP_TAG , str_val) && !times) {
531 | current_array = ×
532 | timeslen = arraylen;
533 | factor = 1000;
534 | } else if (!strcmp(KEYFRAMES_BYTEOFFSET_TAG, str_val) &&
535 | !filepositions) {
536 | current_array = &filepositions;
537 | fileposlen = arraylen;
538 | factor = 1;
539 | } else
540 | // unexpected metatag inside keyframes, will not use such
541 | // metadata for indexing
542 | break;
543 |
544 | if (!(*current_array = av_mallocz(sizeof(**current_array) * arraylen))) {
545 | ret = AVERROR(ENOMEM);
546 | goto finish;
547 | }
548 |
549 | for (i = 0; i < arraylen && avio_tell(ioc) < max_pos - 1; i++) {
550 | double d;
551 | if (avio_r8(ioc) != AMF_DATA_TYPE_NUMBER)
552 | goto invalid;
553 | d = av_int2double(avio_rb64(ioc)) * factor;
554 | if (isnan(d) || d < INT64_MIN || d > INT64_MAX)
555 | goto invalid;
556 | if (avio_feof(ioc))
557 | goto invalid;
558 | current_array[0][i] = d;
559 | }
560 | if (times && filepositions) {
561 | // All done, exiting at a position allowing amf_parse_object
562 | // to finish parsing the object
563 | ret = 0;
564 | break;
565 | }
566 | }
567 |
568 | if (timeslen == fileposlen && fileposlen>1 && max_pos <= filepositions[0]) {
569 | for (i = 0; i < FFMIN(2,fileposlen); i++) {
570 | flv->validate_index[i].pos = filepositions[i];
571 | flv->validate_index[i].dts = times[i];
572 | flv->validate_count = i + 1;
573 | }
574 | flv->keyframe_times = times;
575 | flv->keyframe_filepositions = filepositions;
576 | flv->keyframe_count = timeslen;
577 | times = NULL;
578 | filepositions = NULL;
579 | } else {
580 | invalid:
581 | av_log(s, AV_LOG_WARNING, "Invalid keyframes object, skipping.\n");
582 | }
583 |
584 | finish:
585 | av_freep(×);
586 | av_freep(&filepositions);
587 | avio_seek(ioc, initial_pos, SEEK_SET);
588 | return ret;
589 | }
590 |
591 | static int amf_parse_object(AVFormatContext *s, AVStream *astream,
592 | AVStream *vstream, const char *key,
593 | int64_t max_pos, int depth)
594 | {
595 | AVCodecParameters *apar, *vpar;
596 | FLVContext *flv = s->priv_data;
597 | AVIOContext *ioc;
598 | AMFDataType amf_type;
599 | char str_val[1024];
600 | double num_val;
601 | amf_date date;
602 |
603 | if (depth > MAX_DEPTH)
604 | return AVERROR_PATCHWELCOME;
605 |
606 | num_val = 0;
607 | ioc = s->pb;
608 | if (avio_feof(ioc))
609 | return AVERROR_EOF;
610 | amf_type = avio_r8(ioc);
611 |
612 | switch (amf_type) {
613 | case AMF_DATA_TYPE_NUMBER:
614 | num_val = av_int2double(avio_rb64(ioc));
615 | break;
616 | case AMF_DATA_TYPE_BOOL:
617 | num_val = avio_r8(ioc);
618 | break;
619 | case AMF_DATA_TYPE_STRING:
620 | if (amf_get_string(ioc, str_val, sizeof(str_val)) < 0) {
621 | av_log(s, AV_LOG_ERROR, "AMF_DATA_TYPE_STRING parsing failed\n");
622 | return -1;
623 | }
624 | break;
625 | case AMF_DATA_TYPE_OBJECT:
626 | if (key &&
627 | (ioc->seekable & AVIO_SEEKABLE_NORMAL) &&
628 | !strcmp(KEYFRAMES_TAG, key) && depth == 1)
629 | if (parse_keyframes_index(s, ioc, max_pos) < 0)
630 | av_log(s, AV_LOG_ERROR, "Keyframe index parsing failed\n");
631 | else
632 | add_keyframes_index(s);
633 | while (avio_tell(ioc) < max_pos - 2 &&
634 | amf_get_string(ioc, str_val, sizeof(str_val)) > 0)
635 | if (amf_parse_object(s, astream, vstream, str_val, max_pos,
636 | depth + 1) < 0)
637 | return -1; // if we couldn't skip, bomb out.
638 | if (avio_r8(ioc) != AMF_END_OF_OBJECT) {
639 | av_log(s, AV_LOG_ERROR, "Missing AMF_END_OF_OBJECT in AMF_DATA_TYPE_OBJECT\n");
640 | return -1;
641 | }
642 | break;
643 | case AMF_DATA_TYPE_NULL:
644 | case AMF_DATA_TYPE_UNDEFINED:
645 | case AMF_DATA_TYPE_UNSUPPORTED:
646 | break; // these take up no additional space
647 | case AMF_DATA_TYPE_MIXEDARRAY:
648 | {
649 | unsigned v;
650 | avio_skip(ioc, 4); // skip 32-bit max array index
651 | while (avio_tell(ioc) < max_pos - 2 &&
652 | amf_get_string(ioc, str_val, sizeof(str_val)) > 0)
653 | // this is the only case in which we would want a nested
654 | // parse to not skip over the object
655 | if (amf_parse_object(s, astream, vstream, str_val, max_pos,
656 | depth + 1) < 0)
657 | return -1;
658 | v = avio_r8(ioc);
659 | if (v != AMF_END_OF_OBJECT) {
660 | av_log(s, AV_LOG_ERROR, "Missing AMF_END_OF_OBJECT in AMF_DATA_TYPE_MIXEDARRAY, found %d\n", v);
661 | return -1;
662 | }
663 | break;
664 | }
665 | case AMF_DATA_TYPE_ARRAY:
666 | {
667 | unsigned int arraylen, i;
668 |
669 | arraylen = avio_rb32(ioc);
670 | for (i = 0; i < arraylen && avio_tell(ioc) < max_pos - 1; i++)
671 | if (amf_parse_object(s, NULL, NULL, NULL, max_pos,
672 | depth + 1) < 0)
673 | return -1; // if we couldn't skip, bomb out.
674 | }
675 | break;
676 | case AMF_DATA_TYPE_DATE:
677 | // timestamp (double) and UTC offset (int16)
678 | date.milliseconds = av_int2double(avio_rb64(ioc));
679 | date.timezone = avio_rb16(ioc);
680 | break;
681 | default: // unsupported type, we couldn't skip
682 | av_log(s, AV_LOG_ERROR, "unsupported amf type %d\n", amf_type);
683 | return -1;
684 | }
685 |
686 | if (key) {
687 | apar = astream ? astream->codecpar : NULL;
688 | vpar = vstream ? vstream->codecpar : NULL;
689 |
690 | // stream info doesn't live any deeper than the first object
691 | if (depth == 1) {
692 | if (amf_type == AMF_DATA_TYPE_NUMBER ||
693 | amf_type == AMF_DATA_TYPE_BOOL) {
694 | if (!strcmp(key, "duration"))
695 | s->duration = num_val * AV_TIME_BASE;
696 | else if (!strcmp(key, "videodatarate") &&
697 | 0 <= (int)(num_val * 1024.0))
698 | flv->video_bit_rate = num_val * 1024.0;
699 | else if (!strcmp(key, "audiodatarate") &&
700 | 0 <= (int)(num_val * 1024.0))
701 | flv->audio_bit_rate = num_val * 1024.0;
702 | else if (!strcmp(key, "datastream")) {
703 | AVStream *st = create_stream(s, AVMEDIA_TYPE_SUBTITLE);
704 | if (!st)
705 | return AVERROR(ENOMEM);
706 | st->codecpar->codec_id = AV_CODEC_ID_TEXT;
707 | } else if (!strcmp(key, "framerate")) {
708 | flv->framerate = av_d2q(num_val, 1000);
709 | if (vstream)
710 | vstream->avg_frame_rate = flv->framerate;
711 | } else if (flv->trust_metadata) {
712 | if (!strcmp(key, "videocodecid") && vpar) {
713 | int ret = flv_set_video_codec(s, vstream, num_val, 0);
714 | if (ret < 0)
715 | return ret;
716 | } else if (!strcmp(key, "audiocodecid") && apar) {
717 | int id = ((int)num_val) << FLV_AUDIO_CODECID_OFFSET;
718 | flv_set_audio_codec(s, astream, apar, id);
719 | } else if (!strcmp(key, "audiosamplerate") && apar) {
720 | apar->sample_rate = num_val;
721 | } else if (!strcmp(key, "audiosamplesize") && apar) {
722 | apar->bits_per_coded_sample = num_val;
723 | } else if (!strcmp(key, "stereo") && apar) {
724 | av_channel_layout_default(&apar->ch_layout, num_val + 1);
725 | } else if (!strcmp(key, "width") && vpar) {
726 | vpar->width = num_val;
727 | } else if (!strcmp(key, "height") && vpar) {
728 | vpar->height = num_val;
729 | }
730 | }
731 | }
732 | if (amf_type == AMF_DATA_TYPE_STRING) {
733 | if (!strcmp(key, "encoder")) {
734 | int version = -1;
735 | if (1 == sscanf(str_val, "Open Broadcaster Software v0.%d", &version)) {
736 | if (version > 0 && version <= 655)
737 | flv->broken_sizes = 1;
738 | }
739 | } else if (!strcmp(key, "metadatacreator")) {
740 | if ( !strcmp (str_val, "MEGA")
741 | || !strncmp(str_val, "FlixEngine", 10))
742 | flv->broken_sizes = 1;
743 | }
744 | }
745 | }
746 |
747 | if (amf_type == AMF_DATA_TYPE_OBJECT && s->nb_streams == 1 &&
748 | ((!apar && !strcmp(key, "audiocodecid")) ||
749 | (!vpar && !strcmp(key, "videocodecid"))))
750 | s->ctx_flags &= ~AVFMTCTX_NOHEADER; //If there is either audio/video missing, codecid will be an empty object
751 |
752 | if ((!strcmp(key, "duration") ||
753 | !strcmp(key, "filesize") ||
754 | !strcmp(key, "width") ||
755 | !strcmp(key, "height") ||
756 | !strcmp(key, "videodatarate") ||
757 | !strcmp(key, "framerate") ||
758 | !strcmp(key, "videocodecid") ||
759 | !strcmp(key, "audiodatarate") ||
760 | !strcmp(key, "audiosamplerate") ||
761 | !strcmp(key, "audiosamplesize") ||
762 | !strcmp(key, "stereo") ||
763 | !strcmp(key, "audiocodecid") ||
764 | !strcmp(key, "datastream")) && !flv->dump_full_metadata)
765 | return 0;
766 |
767 | s->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
768 | if (amf_type == AMF_DATA_TYPE_BOOL) {
769 | av_strlcpy(str_val, num_val > 0 ? "true" : "false",
770 | sizeof(str_val));
771 | av_dict_set(&s->metadata, key, str_val, 0);
772 | } else if (amf_type == AMF_DATA_TYPE_NUMBER) {
773 | snprintf(str_val, sizeof(str_val), "%.f", num_val);
774 | av_dict_set(&s->metadata, key, str_val, 0);
775 | } else if (amf_type == AMF_DATA_TYPE_STRING) {
776 | av_dict_set(&s->metadata, key, str_val, 0);
777 | } else if ( amf_type == AMF_DATA_TYPE_DATE
778 | && isfinite(date.milliseconds)
779 | && date.milliseconds > INT64_MIN/1000
780 | && date.milliseconds < INT64_MAX/1000
781 | ) {
782 | // timezone is ignored, since there is no easy way to offset the UTC
783 | // timestamp into the specified timezone
784 | avpriv_dict_set_timestamp(&s->metadata, key, 1000 * (int64_t)date.milliseconds);
785 | }
786 | }
787 |
788 | return 0;
789 | }
790 |
791 | #define TYPE_ONTEXTDATA 1
792 | #define TYPE_ONCAPTION 2
793 | #define TYPE_ONCAPTIONINFO 3
794 | #define TYPE_UNKNOWN 9
795 |
796 | static int flv_read_metabody(AVFormatContext *s, int64_t next_pos)
797 | {
798 | FLVContext *flv = s->priv_data;
799 | AMFDataType type;
800 | AVStream *stream, *astream, *vstream;
801 | AVStream av_unused *dstream;
802 | AVIOContext *ioc;
803 | int i;
804 | char buffer[32];
805 |
806 | astream = NULL;
807 | vstream = NULL;
808 | dstream = NULL;
809 | ioc = s->pb;
810 |
811 | // first object needs to be "onMetaData" string
812 | type = avio_r8(ioc);
813 | if (type != AMF_DATA_TYPE_STRING ||
814 | amf_get_string(ioc, buffer, sizeof(buffer)) < 0)
815 | return TYPE_UNKNOWN;
816 |
817 | if (!strcmp(buffer, "onTextData"))
818 | return TYPE_ONTEXTDATA;
819 |
820 | if (!strcmp(buffer, "onCaption"))
821 | return TYPE_ONCAPTION;
822 |
823 | if (!strcmp(buffer, "onCaptionInfo"))
824 | return TYPE_ONCAPTIONINFO;
825 |
826 | if (strcmp(buffer, "onMetaData") && strcmp(buffer, "onCuePoint") && strcmp(buffer, "|RtmpSampleAccess")) {
827 | av_log(s, AV_LOG_DEBUG, "Unknown type %s\n", buffer);
828 | return TYPE_UNKNOWN;
829 | }
830 |
831 | // find the streams now so that amf_parse_object doesn't need to do
832 | // the lookup every time it is called.
833 | for (i = 0; i < s->nb_streams; i++) {
834 | stream = s->streams[i];
835 | if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
836 | vstream = stream;
837 | flv->last_keyframe_stream_index = i;
838 | } else if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
839 | astream = stream;
840 | if (flv->last_keyframe_stream_index == -1)
841 | flv->last_keyframe_stream_index = i;
842 | } else if (stream->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)
843 | dstream = stream;
844 | }
845 |
846 | // parse the second object (we want a mixed array)
847 | if (amf_parse_object(s, astream, vstream, buffer, next_pos, 0) < 0)
848 | return -1;
849 |
850 | return 0;
851 | }
852 |
853 | static int flv_read_header(AVFormatContext *s)
854 | {
855 | int flags;
856 | FLVContext *flv = s->priv_data;
857 | int offset;
858 | int pre_tag_size = 0;
859 |
860 | /* Actual FLV data at 0xe40000 in KUX file */
861 | if(!strcmp(s->iformat->name, "kux"))
862 | avio_skip(s->pb, 0xe40000);
863 |
864 | avio_skip(s->pb, 4);
865 | flags = avio_r8(s->pb);
866 |
867 | flv->missing_streams = flags & (FLV_HEADER_FLAG_HASVIDEO | FLV_HEADER_FLAG_HASAUDIO);
868 |
869 | s->ctx_flags |= AVFMTCTX_NOHEADER;
870 |
871 | offset = avio_rb32(s->pb);
872 | avio_seek(s->pb, offset, SEEK_SET);
873 |
874 | /* Annex E. The FLV File Format
875 | * E.3 TheFLVFileBody
876 | * Field Type Comment
877 | * PreviousTagSize0 UI32 Always 0
878 | * */
879 | pre_tag_size = avio_rb32(s->pb);
880 | if (pre_tag_size) {
881 | av_log(s, AV_LOG_WARNING, "Read FLV header error, input file is not a standard flv format, first PreviousTagSize0 always is 0\n");
882 | }
883 |
884 | s->start_time = 0;
885 | flv->sum_flv_tag_size = 0;
886 | flv->last_keyframe_stream_index = -1;
887 |
888 | return 0;
889 | }
890 |
891 | static int flv_read_close(AVFormatContext *s)
892 | {
893 | int i;
894 | FLVContext *flv = s->priv_data;
895 | for (i=0; inew_extradata[i]);
897 | av_freep(&flv->keyframe_times);
898 | av_freep(&flv->keyframe_filepositions);
899 | return 0;
900 | }
901 |
902 | static int flv_get_extradata(AVFormatContext *s, AVStream *st, int size)
903 | {
904 | int ret;
905 | if (!size)
906 | return 0;
907 |
908 | if ((ret = ff_get_extradata(s, st->codecpar, s->pb, size)) < 0)
909 | return ret;
910 | ffstream(st)->need_context_update = 1;
911 | return 0;
912 | }
913 |
914 | static int flv_queue_extradata(FLVContext *flv, AVIOContext *pb, int stream,
915 | int size)
916 | {
917 | if (!size)
918 | return 0;
919 |
920 | av_free(flv->new_extradata[stream]);
921 | flv->new_extradata[stream] = av_mallocz(size +
922 | AV_INPUT_BUFFER_PADDING_SIZE);
923 | if (!flv->new_extradata[stream])
924 | return AVERROR(ENOMEM);
925 | flv->new_extradata_size[stream] = size;
926 | avio_read(pb, flv->new_extradata[stream], size);
927 | return 0;
928 | }
929 |
930 | static void clear_index_entries(AVFormatContext *s, int64_t pos)
931 | {
932 | av_log(s, AV_LOG_WARNING,
933 | "Found invalid index entries, clearing the index.\n");
934 | for (unsigned i = 0; i < s->nb_streams; i++) {
935 | FFStream *const sti = ffstream(s->streams[i]);
936 | int out = 0;
937 | /* Remove all index entries that point to >= pos */
938 | for (int j = 0; j < sti->nb_index_entries; j++)
939 | if (sti->index_entries[j].pos < pos)
940 | sti->index_entries[out++] = sti->index_entries[j];
941 | sti->nb_index_entries = out;
942 | }
943 | }
944 |
945 | static int amf_skip_tag(AVIOContext *pb, AMFDataType type, int depth)
946 | {
947 | int nb = -1, ret, parse_name = 1;
948 |
949 | if (depth > MAX_DEPTH)
950 | return AVERROR_PATCHWELCOME;
951 |
952 | if (avio_feof(pb))
953 | return AVERROR_EOF;
954 |
955 | switch (type) {
956 | case AMF_DATA_TYPE_NUMBER:
957 | avio_skip(pb, 8);
958 | break;
959 | case AMF_DATA_TYPE_BOOL:
960 | avio_skip(pb, 1);
961 | break;
962 | case AMF_DATA_TYPE_STRING:
963 | avio_skip(pb, avio_rb16(pb));
964 | break;
965 | case AMF_DATA_TYPE_ARRAY:
966 | parse_name = 0;
967 | case AMF_DATA_TYPE_MIXEDARRAY:
968 | nb = avio_rb32(pb);
969 | if (nb < 0)
970 | return AVERROR_INVALIDDATA;
971 | case AMF_DATA_TYPE_OBJECT:
972 | while(!pb->eof_reached && (nb-- > 0 || type != AMF_DATA_TYPE_ARRAY)) {
973 | if (parse_name) {
974 | int size = avio_rb16(pb);
975 | if (!size) {
976 | avio_skip(pb, 1);
977 | break;
978 | }
979 | avio_skip(pb, size);
980 | }
981 | if ((ret = amf_skip_tag(pb, avio_r8(pb), depth + 1)) < 0)
982 | return ret;
983 | }
984 | break;
985 | case AMF_DATA_TYPE_NULL:
986 | case AMF_DATA_TYPE_OBJECT_END:
987 | break;
988 | default:
989 | return AVERROR_INVALIDDATA;
990 | }
991 | return 0;
992 | }
993 |
994 | static int flv_data_packet(AVFormatContext *s, AVPacket *pkt,
995 | int64_t dts, int64_t next)
996 | {
997 | AVIOContext *pb = s->pb;
998 | AVStream *st = NULL;
999 | char buf[20];
1000 | int ret = AVERROR_INVALIDDATA;
1001 | int i, length = -1;
1002 | int array = 0;
1003 |
1004 | switch (avio_r8(pb)) {
1005 | case AMF_DATA_TYPE_ARRAY:
1006 | array = 1;
1007 | case AMF_DATA_TYPE_MIXEDARRAY:
1008 | avio_seek(pb, 4, SEEK_CUR);
1009 | case AMF_DATA_TYPE_OBJECT:
1010 | break;
1011 | default:
1012 | goto skip;
1013 | }
1014 |
1015 | while (array || (ret = amf_get_string(pb, buf, sizeof(buf))) > 0) {
1016 | AMFDataType type = avio_r8(pb);
1017 | if (type == AMF_DATA_TYPE_STRING && (array || !strcmp(buf, "text"))) {
1018 | length = avio_rb16(pb);
1019 | ret = av_get_packet(pb, pkt, length);
1020 | if (ret < 0)
1021 | goto skip;
1022 | else
1023 | break;
1024 | } else {
1025 | if ((ret = amf_skip_tag(pb, type, 0)) < 0)
1026 | goto skip;
1027 | }
1028 | }
1029 |
1030 | if (length < 0) {
1031 | ret = AVERROR_INVALIDDATA;
1032 | goto skip;
1033 | }
1034 |
1035 | for (i = 0; i < s->nb_streams; i++) {
1036 | st = s->streams[i];
1037 | if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)
1038 | break;
1039 | }
1040 |
1041 | if (i == s->nb_streams) {
1042 | st = create_stream(s, AVMEDIA_TYPE_SUBTITLE);
1043 | if (!st)
1044 | return AVERROR(ENOMEM);
1045 | st->codecpar->codec_id = AV_CODEC_ID_TEXT;
1046 | }
1047 |
1048 | pkt->dts = dts;
1049 | pkt->pts = dts;
1050 | pkt->size = ret;
1051 |
1052 | pkt->stream_index = st->index;
1053 | pkt->flags |= AV_PKT_FLAG_KEY;
1054 |
1055 | skip:
1056 | avio_seek(s->pb, next + 4, SEEK_SET);
1057 |
1058 | return ret;
1059 | }
1060 |
1061 | static int resync(AVFormatContext *s)
1062 | {
1063 | FLVContext *flv = s->priv_data;
1064 | int64_t i;
1065 | int64_t pos = avio_tell(s->pb);
1066 |
1067 | for (i=0; !avio_feof(s->pb); i++) {
1068 | int j = i & (RESYNC_BUFFER_SIZE-1);
1069 | int j1 = j + RESYNC_BUFFER_SIZE;
1070 | flv->resync_buffer[j ] =
1071 | flv->resync_buffer[j1] = avio_r8(s->pb);
1072 |
1073 | if (i >= 8 && pos) {
1074 | uint8_t *d = flv->resync_buffer + j1 - 8;
1075 | if (d[0] == 'F' &&
1076 | d[1] == 'L' &&
1077 | d[2] == 'V' &&
1078 | d[3] < 5 && d[5] == 0) {
1079 | av_log(s, AV_LOG_WARNING, "Concatenated FLV detected, might fail to demux, decode and seek %"PRId64"\n", flv->last_ts);
1080 | flv->time_offset = flv->last_ts + 1;
1081 | flv->time_pos = avio_tell(s->pb);
1082 | }
1083 | }
1084 |
1085 | if (i > 22) {
1086 | unsigned lsize2 = AV_RB32(flv->resync_buffer + j1 - 4);
1087 | if (lsize2 >= 11 && lsize2 + 8LL < FFMIN(i, RESYNC_BUFFER_SIZE)) {
1088 | unsigned size2 = AV_RB24(flv->resync_buffer + j1 - lsize2 + 1 - 4);
1089 | unsigned lsize1 = AV_RB32(flv->resync_buffer + j1 - lsize2 - 8);
1090 | if (lsize1 >= 11 && lsize1 + 8LL + lsize2 < FFMIN(i, RESYNC_BUFFER_SIZE)) {
1091 | unsigned size1 = AV_RB24(flv->resync_buffer + j1 - lsize1 + 1 - lsize2 - 8);
1092 | if (size1 == lsize1 - 11 && size2 == lsize2 - 11) {
1093 | avio_seek(s->pb, pos + i - lsize1 - lsize2 - 8, SEEK_SET);
1094 | return 1;
1095 | }
1096 | }
1097 | }
1098 | }
1099 | }
1100 | return AVERROR_EOF;
1101 | }
1102 |
1103 | static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
1104 | {
1105 | FLVContext *flv = s->priv_data;
1106 | int ret, i, size, flags;
1107 | enum FlvTagType type;
1108 | int stream_type=-1;
1109 | int64_t next, pos, meta_pos;
1110 | int64_t dts, pts = AV_NOPTS_VALUE;
1111 | int av_uninit(channels);
1112 | int av_uninit(sample_rate);
1113 | AVStream *st = NULL;
1114 | int last = -1;
1115 | int orig_size;
1116 |
1117 | retry:
1118 | /* pkt size is repeated at end. skip it */
1119 | pos = avio_tell(s->pb);
1120 | type = (avio_r8(s->pb) & 0x1F);
1121 | orig_size =
1122 | size = avio_rb24(s->pb);
1123 | flv->sum_flv_tag_size += size + 11LL;
1124 | dts = avio_rb24(s->pb);
1125 | dts |= (unsigned)avio_r8(s->pb) << 24;
1126 | av_log(s, AV_LOG_TRACE, "type:%d, size:%d, last:%d, dts:%"PRId64" pos:%"PRId64"\n", type, size, last, dts, avio_tell(s->pb));
1127 | if (avio_feof(s->pb))
1128 | return AVERROR_EOF;
1129 | avio_skip(s->pb, 3); /* stream id, always 0 */
1130 | flags = 0;
1131 |
1132 | if (flv->validate_next < flv->validate_count) {
1133 | int64_t validate_pos = flv->validate_index[flv->validate_next].pos;
1134 | if (pos == validate_pos) {
1135 | if (FFABS(dts - flv->validate_index[flv->validate_next].dts) <=
1136 | VALIDATE_INDEX_TS_THRESH) {
1137 | flv->validate_next++;
1138 | } else {
1139 | clear_index_entries(s, validate_pos);
1140 | flv->validate_count = 0;
1141 | }
1142 | } else if (pos > validate_pos) {
1143 | clear_index_entries(s, validate_pos);
1144 | flv->validate_count = 0;
1145 | }
1146 | }
1147 |
1148 | if (size == 0) {
1149 | ret = FFERROR_REDO;
1150 | goto leave;
1151 | }
1152 |
1153 | next = size + avio_tell(s->pb);
1154 |
1155 | if (type == FLV_TAG_TYPE_AUDIO) {
1156 | stream_type = FLV_STREAM_TYPE_AUDIO;
1157 | flags = avio_r8(s->pb);
1158 | size--;
1159 | } else if (type == FLV_TAG_TYPE_VIDEO) {
1160 | stream_type = FLV_STREAM_TYPE_VIDEO;
1161 | flags = avio_r8(s->pb);
1162 | size--;
1163 | if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_VIDEO_INFO_CMD)
1164 | goto skip;
1165 | } else if (type == FLV_TAG_TYPE_META) {
1166 | stream_type=FLV_STREAM_TYPE_SUBTITLE;
1167 | if (size > 13 + 1 + 4) { // Header-type metadata stuff
1168 | int type;
1169 | meta_pos = avio_tell(s->pb);
1170 | type = flv_read_metabody(s, next);
1171 | if (type == 0 && dts == 0 || type < 0) {
1172 | if (type < 0 && flv->validate_count &&
1173 | flv->validate_index[0].pos > next &&
1174 | flv->validate_index[0].pos - 4 < next) {
1175 | av_log(s, AV_LOG_WARNING, "Adjusting next position due to index mismatch\n");
1176 | next = flv->validate_index[0].pos - 4;
1177 | }
1178 | goto skip;
1179 | } else if (type == TYPE_ONTEXTDATA) {
1180 | avpriv_request_sample(s, "OnTextData packet");
1181 | return flv_data_packet(s, pkt, dts, next);
1182 | } else if (type == TYPE_ONCAPTION) {
1183 | return flv_data_packet(s, pkt, dts, next);
1184 | } else if (type == TYPE_UNKNOWN) {
1185 | stream_type = FLV_STREAM_TYPE_DATA;
1186 | }
1187 | avio_seek(s->pb, meta_pos, SEEK_SET);
1188 | }
1189 | } else {
1190 | av_log(s, AV_LOG_DEBUG,
1191 | "Skipping flv packet: type %d, size %d, flags %d.\n",
1192 | type, size, flags);
1193 | skip:
1194 | if (avio_seek(s->pb, next, SEEK_SET) != next) {
1195 | // This can happen if flv_read_metabody above read past
1196 | // next, on a non-seekable input, and the preceding data has
1197 | // been flushed out from the IO buffer.
1198 | av_log(s, AV_LOG_ERROR, "Unable to seek to the next packet\n");
1199 | return AVERROR_INVALIDDATA;
1200 | }
1201 | ret = FFERROR_REDO;
1202 | goto leave;
1203 | }
1204 |
1205 | /* skip empty data packets */
1206 | if (!size) {
1207 | ret = FFERROR_REDO;
1208 | goto leave;
1209 | }
1210 |
1211 | /* now find stream */
1212 | for (i = 0; i < s->nb_streams; i++) {
1213 | st = s->streams[i];
1214 | if (stream_type == FLV_STREAM_TYPE_AUDIO) {
1215 | if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
1216 | (s->audio_codec_id || flv_same_audio_codec(st->codecpar, flags)))
1217 | break;
1218 | } else if (stream_type == FLV_STREAM_TYPE_VIDEO) {
1219 | if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
1220 | (s->video_codec_id || flv_same_video_codec(s, st->codecpar, flags)))
1221 | break;
1222 | } else if (stream_type == FLV_STREAM_TYPE_SUBTITLE) {
1223 | if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)
1224 | break;
1225 | } else if (stream_type == FLV_STREAM_TYPE_DATA) {
1226 | if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA)
1227 | break;
1228 | }
1229 | }
1230 | if (i == s->nb_streams) {
1231 | static const enum AVMediaType stream_types[] = {AVMEDIA_TYPE_VIDEO, AVMEDIA_TYPE_AUDIO, AVMEDIA_TYPE_SUBTITLE, AVMEDIA_TYPE_DATA};
1232 | st = create_stream(s, stream_types[stream_type]);
1233 | if (!st)
1234 | return AVERROR(ENOMEM);
1235 | }
1236 | av_log(s, AV_LOG_TRACE, "%d %X %d \n", stream_type, flags, st->discard);
1237 |
1238 | if (flv->time_pos <= pos) {
1239 | dts += flv->time_offset;
1240 | }
1241 |
1242 | if (stream_type == FLV_STREAM_TYPE_VIDEO && IS_EXT_HEADER(flags)) {
1243 | if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
1244 | (EXT_HEADER_IS_KEYFRAME(flags) ||
1245 | stream_type == FLV_STREAM_TYPE_AUDIO))
1246 | av_add_index_entry(st, pos, dts, size, 0, AVINDEX_KEYFRAME);
1247 | } else {
1248 | if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
1249 | ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY ||
1250 | stream_type == FLV_STREAM_TYPE_AUDIO))
1251 | av_add_index_entry(st, pos, dts, size, 0, AVINDEX_KEYFRAME);
1252 | }
1253 |
1254 | if (stream_type == FLV_STREAM_TYPE_VIDEO && IS_EXT_HEADER(flags)) {
1255 | if ((st->discard >= AVDISCARD_NONKEY && !(EXT_HEADER_IS_KEYFRAME(flags) || stream_type == FLV_STREAM_TYPE_AUDIO)) ||
1256 | (st->discard >= AVDISCARD_BIDIR && ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_DISP_INTER && stream_type == FLV_STREAM_TYPE_VIDEO)) ||
1257 | st->discard >= AVDISCARD_ALL) {
1258 | avio_seek(s->pb, next, SEEK_SET);
1259 | ret = FFERROR_REDO;
1260 | goto leave;
1261 | }
1262 | } else {
1263 | if ((st->discard >= AVDISCARD_NONKEY && !((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY || stream_type == FLV_STREAM_TYPE_AUDIO)) ||
1264 | (st->discard >= AVDISCARD_BIDIR && ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_DISP_INTER && stream_type == FLV_STREAM_TYPE_VIDEO)) ||
1265 | st->discard >= AVDISCARD_ALL) {
1266 | avio_seek(s->pb, next, SEEK_SET);
1267 | ret = FFERROR_REDO;
1268 | goto leave;
1269 | }
1270 | }
1271 | // if not streamed and no duration from metadata then seek to end to find
1272 | // the duration from the timestamps
1273 | if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
1274 | (!s->duration || s->duration == AV_NOPTS_VALUE) &&
1275 | !flv->searched_for_end) {
1276 | int size;
1277 | const int64_t pos = avio_tell(s->pb);
1278 | // Read the last 4 bytes of the file, this should be the size of the
1279 | // previous FLV tag. Use the timestamp of its payload as duration.
1280 | int64_t fsize = avio_size(s->pb);
1281 | retry_duration:
1282 | avio_seek(s->pb, fsize - 4, SEEK_SET);
1283 | size = avio_rb32(s->pb);
1284 | if (size > 0 && size < fsize) {
1285 | // Seek to the start of the last FLV tag at position (fsize - 4 - size)
1286 | // but skip the byte indicating the type.
1287 | avio_seek(s->pb, fsize - 3 - size, SEEK_SET);
1288 | if (size == avio_rb24(s->pb) + 11) {
1289 | uint32_t ts = avio_rb24(s->pb);
1290 | ts |= (unsigned)avio_r8(s->pb) << 24;
1291 | if (ts)
1292 | s->duration = ts * (int64_t)AV_TIME_BASE / 1000;
1293 | else if (fsize >= 8 && fsize - 8 >= size) {
1294 | fsize -= size+4;
1295 | goto retry_duration;
1296 | }
1297 | }
1298 | }
1299 |
1300 | avio_seek(s->pb, pos, SEEK_SET);
1301 | flv->searched_for_end = 1;
1302 | }
1303 |
1304 | if (stream_type == FLV_STREAM_TYPE_AUDIO) {
1305 | int bits_per_coded_sample;
1306 | channels = (flags & FLV_AUDIO_CHANNEL_MASK) == FLV_STEREO ? 2 : 1;
1307 | sample_rate = 44100 << ((flags & FLV_AUDIO_SAMPLERATE_MASK) >>
1308 | FLV_AUDIO_SAMPLERATE_OFFSET) >> 3;
1309 | bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8;
1310 | if (!av_channel_layout_check(&st->codecpar->ch_layout) ||
1311 | !st->codecpar->sample_rate ||
1312 | !st->codecpar->bits_per_coded_sample) {
1313 | av_channel_layout_default(&st->codecpar->ch_layout, channels);
1314 | st->codecpar->sample_rate = sample_rate;
1315 | st->codecpar->bits_per_coded_sample = bits_per_coded_sample;
1316 | }
1317 | if (!st->codecpar->codec_id) {
1318 | flv_set_audio_codec(s, st, st->codecpar,
1319 | flags & FLV_AUDIO_CODECID_MASK);
1320 | flv->last_sample_rate =
1321 | sample_rate = st->codecpar->sample_rate;
1322 | flv->last_channels =
1323 | channels = st->codecpar->ch_layout.nb_channels;
1324 | } else {
1325 | AVCodecParameters *par = avcodec_parameters_alloc();
1326 | if (!par) {
1327 | ret = AVERROR(ENOMEM);
1328 | goto leave;
1329 | }
1330 | par->sample_rate = sample_rate;
1331 | par->bits_per_coded_sample = bits_per_coded_sample;
1332 | flv_set_audio_codec(s, st, par, flags & FLV_AUDIO_CODECID_MASK);
1333 | sample_rate = par->sample_rate;
1334 | avcodec_parameters_free(&par);
1335 | }
1336 | } else if (stream_type == FLV_STREAM_TYPE_VIDEO) {
1337 | int ret = flv_set_video_codec(s, st, flags, 1);
1338 | if (ret < 0)
1339 | return ret;
1340 | size -= ret;
1341 | } else if (stream_type == FLV_STREAM_TYPE_SUBTITLE) {
1342 | st->codecpar->codec_id = AV_CODEC_ID_TEXT;
1343 | } else if (stream_type == FLV_STREAM_TYPE_DATA) {
1344 | st->codecpar->codec_id = AV_CODEC_ID_NONE; // Opaque AMF data
1345 | }
1346 |
1347 | if (st->codecpar->codec_id == AV_CODEC_ID_AAC ||
1348 | st->codecpar->codec_id == AV_CODEC_ID_H264 ||
1349 | st->codecpar->codec_id == AV_CODEC_ID_MPEG4 ||
1350 | st->codecpar->codec_id == AV_CODEC_ID_HEVC ||
1351 | st->codecpar->codec_id == AV_CODEC_ID_VP8 ||
1352 | st->codecpar->codec_id == AV_CODEC_ID_VP9 ||
1353 | st->codecpar->codec_id == AV_CODEC_ID_OPUS) {
1354 | int type;
1355 |
1356 | if (stream_type == FLV_STREAM_TYPE_VIDEO && IS_EXT_HEADER(flags)) {
1357 | type = GET_PACKET_TYPE(flags);
1358 | } else {
1359 | type = avio_r8(s->pb);
1360 | size--;
1361 | }
1362 |
1363 | if (size < 0) {
1364 | ret = AVERROR_INVALIDDATA;
1365 | goto leave;
1366 | }
1367 |
1368 | if (st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_MPEG4
1369 | || st->codecpar->codec_id == AV_CODEC_ID_HEVC || st->codecpar->codec_id == AV_CODEC_ID_VP8
1370 | || st->codecpar->codec_id == AV_CODEC_ID_VP9 || st->codecpar->codec_id == AV_CODEC_ID_AV1) {
1371 | if (!IS_EXT_HEADER(flags) || (IS_EXT_HEADER(flags) && type == PACKETTYPE_FRAMES)) {
1372 | // sign extension
1373 | int32_t cts = (avio_rb24(s->pb) + 0xff800000) ^ 0xff800000;
1374 | if (IS_EXT_HEADER(flags)) {
1375 | size -= 3;
1376 | }
1377 | pts = av_sat_add64(dts, cts);
1378 | if (cts < 0) { // dts might be wrong
1379 | if (!flv->wrong_dts)
1380 | av_log(s, AV_LOG_WARNING,
1381 | "Negative cts:0x%08x, previous timestamps might be wrong.\n", cts);
1382 | flv->wrong_dts = 1;
1383 | } else if (FFABS(dts - pts) > 1000*60*15) {
1384 | av_log(s, AV_LOG_WARNING,
1385 | "invalid timestamps %"PRId64" %"PRId64"\n", dts, pts);
1386 | dts = pts = AV_NOPTS_VALUE;
1387 | }
1388 | }
1389 | }
1390 | if (type == 0 && (!st->codecpar->extradata || st->codecpar->codec_id == AV_CODEC_ID_AAC ||
1391 | st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_HEVC ||
1392 | st->codecpar->codec_id == AV_CODEC_ID_VP8 || st->codecpar->codec_id == AV_CODEC_ID_VP9 ||
1393 | st->codecpar->codec_id == AV_CODEC_ID_OPUS)) {
1394 | AVDictionaryEntry *t;
1395 |
1396 | if (st->codecpar->extradata) {
1397 | if ((ret = flv_queue_extradata(flv, s->pb, stream_type, size)) < 0)
1398 | return ret;
1399 | ret = FFERROR_REDO;
1400 | goto leave;
1401 | }
1402 | if ((ret = flv_get_extradata(s, st, size)) < 0)
1403 | return ret;
1404 |
1405 | /* Workaround for buggy Omnia A/XE encoder */
1406 | t = av_dict_get(s->metadata, "Encoder", NULL, 0);
1407 | if (st->codecpar->codec_id == AV_CODEC_ID_AAC && t && !strcmp(t->value, "Omnia A/XE"))
1408 | st->codecpar->extradata_size = 2;
1409 |
1410 | ret = FFERROR_REDO;
1411 | goto leave;
1412 | }
1413 | }
1414 |
1415 | /* skip empty data packets */
1416 | if (!size) {
1417 | ret = FFERROR_REDO;
1418 | goto leave;
1419 | }
1420 |
1421 | ret = av_get_packet(s->pb, pkt, size);
1422 | if (ret < 0)
1423 | return ret;
1424 | pkt->dts = dts;
1425 | pkt->pts = pts == AV_NOPTS_VALUE ? dts : pts;
1426 | pkt->stream_index = st->index;
1427 | pkt->pos = pos;
1428 | if (flv->new_extradata[stream_type]) {
1429 | int ret = av_packet_add_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
1430 | flv->new_extradata[stream_type],
1431 | flv->new_extradata_size[stream_type]);
1432 | if (ret >= 0) {
1433 | flv->new_extradata[stream_type] = NULL;
1434 | flv->new_extradata_size[stream_type] = 0;
1435 | }
1436 | }
1437 | if (stream_type == FLV_STREAM_TYPE_AUDIO &&
1438 | (sample_rate != flv->last_sample_rate ||
1439 | channels != flv->last_channels)) {
1440 | flv->last_sample_rate = sample_rate;
1441 | flv->last_channels = channels;
1442 | ff_add_param_change(pkt, channels, 0, sample_rate, 0, 0);
1443 | }
1444 |
1445 | if (stream_type == FLV_STREAM_TYPE_VIDEO && IS_EXT_HEADER(flags)) {
1446 | if (stream_type == FLV_STREAM_TYPE_AUDIO ||
1447 | EXT_HEADER_IS_KEYFRAME(flags) ||
1448 | stream_type == FLV_STREAM_TYPE_SUBTITLE ||
1449 | stream_type == FLV_STREAM_TYPE_DATA)
1450 | pkt->flags |= AV_PKT_FLAG_KEY;
1451 |
1452 | } else {
1453 | if (stream_type == FLV_STREAM_TYPE_AUDIO ||
1454 | (flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY ||
1455 | stream_type == FLV_STREAM_TYPE_SUBTITLE ||
1456 | stream_type == FLV_STREAM_TYPE_DATA)
1457 | pkt->flags |= AV_PKT_FLAG_KEY;
1458 | }
1459 | leave:
1460 | last = avio_rb32(s->pb);
1461 | if (!flv->trust_datasize) {
1462 | if (last != orig_size + 11 && last != orig_size + 10 &&
1463 | !avio_feof(s->pb) &&
1464 | (last != orig_size || !last) && last != flv->sum_flv_tag_size &&
1465 | !flv->broken_sizes) {
1466 | av_log(s, AV_LOG_ERROR, "Packet mismatch %d %d %"PRId64"\n", last, orig_size + 11, flv->sum_flv_tag_size);
1467 | avio_seek(s->pb, pos + 1, SEEK_SET);
1468 | ret = resync(s);
1469 | av_packet_unref(pkt);
1470 | if (ret >= 0) {
1471 | goto retry;
1472 | }
1473 | }
1474 | }
1475 |
1476 | if (ret >= 0)
1477 | flv->last_ts = pkt->dts;
1478 |
1479 | return ret;
1480 | }
1481 |
1482 | static int flv_read_seek(AVFormatContext *s, int stream_index,
1483 | int64_t ts, int flags)
1484 | {
1485 | FLVContext *flv = s->priv_data;
1486 | flv->validate_count = 0;
1487 | return avio_seek_time(s->pb, stream_index, ts, flags);
1488 | }
1489 |
1490 | #define OFFSET(x) offsetof(FLVContext, x)
1491 | #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
1492 | static const AVOption options[] = {
1493 | { "flv_metadata", "Allocate streams according to the onMetaData array", OFFSET(trust_metadata), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VD },
1494 | { "flv_full_metadata", "Dump full metadata of the onMetadata", OFFSET(dump_full_metadata), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VD },
1495 | { "flv_ignore_prevtag", "Ignore the Size of previous tag", OFFSET(trust_datasize), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VD },
1496 | { "missing_streams", "", OFFSET(missing_streams), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 0xFF, VD | AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY },
1497 | { NULL }
1498 | };
1499 |
1500 | static const AVClass flv_kux_class = {
1501 | .class_name = "(live) flv/kux demuxer",
1502 | .item_name = av_default_item_name,
1503 | .option = options,
1504 | .version = LIBAVUTIL_VERSION_INT,
1505 | };
1506 |
1507 | const AVInputFormat ff_flv_demuxer = {
1508 | .name = "flv",
1509 | .long_name = NULL_IF_CONFIG_SMALL("FLV (Flash Video)"),
1510 | .priv_data_size = sizeof(FLVContext),
1511 | .read_probe = flv_probe,
1512 | .read_header = flv_read_header,
1513 | .read_packet = flv_read_packet,
1514 | .read_seek = flv_read_seek,
1515 | .read_close = flv_read_close,
1516 | .extensions = "flv",
1517 | .priv_class = &flv_kux_class,
1518 | };
1519 |
1520 | const AVInputFormat ff_live_flv_demuxer = {
1521 | .name = "live_flv",
1522 | .long_name = NULL_IF_CONFIG_SMALL("live RTMP FLV (Flash Video)"),
1523 | .priv_data_size = sizeof(FLVContext),
1524 | .read_probe = live_flv_probe,
1525 | .read_header = flv_read_header,
1526 | .read_packet = flv_read_packet,
1527 | .read_seek = flv_read_seek,
1528 | .read_close = flv_read_close,
1529 | .extensions = "flv",
1530 | .priv_class = &flv_kux_class,
1531 | .flags = AVFMT_TS_DISCONT
1532 | };
1533 |
1534 | const AVInputFormat ff_kux_demuxer = {
1535 | .name = "kux",
1536 | .long_name = NULL_IF_CONFIG_SMALL("KUX (YouKu)"),
1537 | .priv_data_size = sizeof(FLVContext),
1538 | .read_probe = kux_probe,
1539 | .read_header = flv_read_header,
1540 | .read_packet = flv_read_packet,
1541 | .read_seek = flv_read_seek,
1542 | .read_close = flv_read_close,
1543 | .extensions = "kux",
1544 | .priv_class = &flv_kux_class,
1545 | };
1546 |
--------------------------------------------------------------------------------
/flvenc.c:
--------------------------------------------------------------------------------
1 | /*
2 | * FLV muxer
3 | * Copyright (c) 2003 The FFmpeg Project
4 | *
5 | * This file is part of FFmpeg.
6 | *
7 | * FFmpeg is free software; you can redistribute it and/or
8 | * modify it under the terms of the GNU Lesser General Public
9 | * License as published by the Free Software Foundation; either
10 | * version 2.1 of the License, or (at your option) any later version.
11 | *
12 | * FFmpeg is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * Lesser General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public
18 | * License along with FFmpeg; if not, write to the Free Software
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 | */
21 |
22 | #include "libavutil/intreadwrite.h"
23 | #include "libavutil/dict.h"
24 | #include "libavutil/intfloat.h"
25 | #include "libavutil/avassert.h"
26 | #include "libavutil/mathematics.h"
27 | #include "libavcodec/codec_desc.h"
28 | #include "libavcodec/mpeg4audio.h"
29 | #include "avio.h"
30 | #include "avc.h"
31 | #include "avformat.h"
32 | #include "flv.h"
33 | #include "internal.h"
34 | #include "mux.h"
35 | #include "libavutil/opt.h"
36 | #include "libavcodec/put_bits.h"
37 |
38 |
39 | static const AVCodecTag flv_video_codec_ids[] = {
40 | { AV_CODEC_ID_FLV1, FLV_CODECID_H263 },
41 | { AV_CODEC_ID_H263, FLV_CODECID_REALH263 },
42 | { AV_CODEC_ID_MPEG4, FLV_CODECID_MPEG4 },
43 | { AV_CODEC_ID_FLASHSV, FLV_CODECID_SCREEN },
44 | { AV_CODEC_ID_FLASHSV2, FLV_CODECID_SCREEN2 },
45 | { AV_CODEC_ID_VP6F, FLV_CODECID_VP6 },
46 | { AV_CODEC_ID_VP6, FLV_CODECID_VP6 },
47 | { AV_CODEC_ID_VP6A, FLV_CODECID_VP6A },
48 | { AV_CODEC_ID_H264, FLV_CODECID_H264 },
49 | { AV_CODEC_ID_HEVC, FLV_CODECID_HEVC },
50 | { AV_CODEC_ID_VP8, FLV_CODECID_VP8 },
51 | { AV_CODEC_ID_VP9, FLV_CODECID_VP9 },
52 | { AV_CODEC_ID_NONE, 0 }
53 | };
54 |
55 | static const AVCodecTag flv_audio_codec_ids[] = {
56 | { AV_CODEC_ID_MP3, FLV_CODECID_MP3 >> FLV_AUDIO_CODECID_OFFSET },
57 | { AV_CODEC_ID_PCM_U8, FLV_CODECID_PCM >> FLV_AUDIO_CODECID_OFFSET },
58 | { AV_CODEC_ID_PCM_S16BE, FLV_CODECID_PCM >> FLV_AUDIO_CODECID_OFFSET },
59 | { AV_CODEC_ID_PCM_S16LE, FLV_CODECID_PCM_LE >> FLV_AUDIO_CODECID_OFFSET },
60 | { AV_CODEC_ID_ADPCM_SWF, FLV_CODECID_ADPCM >> FLV_AUDIO_CODECID_OFFSET },
61 | { AV_CODEC_ID_AAC, FLV_CODECID_AAC >> FLV_AUDIO_CODECID_OFFSET },
62 | { AV_CODEC_ID_OPUS, FLV_CODECID_OPUS >> FLV_AUDIO_CODECID_OFFSET },
63 | { AV_CODEC_ID_NELLYMOSER, FLV_CODECID_NELLYMOSER >> FLV_AUDIO_CODECID_OFFSET },
64 | { AV_CODEC_ID_PCM_MULAW, FLV_CODECID_PCM_MULAW >> FLV_AUDIO_CODECID_OFFSET },
65 | { AV_CODEC_ID_PCM_ALAW, FLV_CODECID_PCM_ALAW >> FLV_AUDIO_CODECID_OFFSET },
66 | { AV_CODEC_ID_SPEEX, FLV_CODECID_SPEEX >> FLV_AUDIO_CODECID_OFFSET },
67 | { AV_CODEC_ID_NONE, 0 }
68 | };
69 |
70 | typedef enum {
71 | FLV_AAC_SEQ_HEADER_DETECT = (1 << 0),
72 | FLV_NO_SEQUENCE_END = (1 << 1),
73 | FLV_ADD_KEYFRAME_INDEX = (1 << 2),
74 | FLV_NO_METADATA = (1 << 3),
75 | FLV_NO_DURATION_FILESIZE = (1 << 4),
76 | FLV_EXTERN_HEADER = (1 << 5),
77 | } FLVFlags;
78 |
79 | typedef struct FLVFileposition {
80 | int64_t keyframe_position;
81 | double keyframe_timestamp;
82 | struct FLVFileposition *next;
83 | } FLVFileposition;
84 |
85 | typedef struct FLVContext {
86 | AVClass *av_class;
87 | int reserved;
88 | int64_t duration_offset;
89 | int64_t filesize_offset;
90 | int64_t duration;
91 | int64_t delay; ///< first dts delay (needed for AVC & Speex)
92 |
93 | int64_t datastart_offset;
94 | int64_t datasize_offset;
95 | int64_t datasize;
96 | int64_t videosize_offset;
97 | int64_t videosize;
98 | int64_t audiosize_offset;
99 | int64_t audiosize;
100 |
101 | int64_t metadata_size_pos;
102 | int64_t metadata_totalsize_pos;
103 | int64_t metadata_totalsize;
104 | int64_t keyframe_index_size;
105 |
106 | int64_t lasttimestamp_offset;
107 | double lasttimestamp;
108 | int64_t lastkeyframetimestamp_offset;
109 | double lastkeyframetimestamp;
110 | int64_t lastkeyframelocation_offset;
111 | int64_t lastkeyframelocation;
112 |
113 | int64_t keyframes_info_offset;
114 |
115 | int64_t filepositions_count;
116 | FLVFileposition *filepositions;
117 | FLVFileposition *head_filepositions;
118 |
119 | AVCodecParameters *audio_par;
120 | AVCodecParameters *video_par;
121 | double framerate;
122 | AVCodecParameters *data_par;
123 |
124 | int flags;
125 | } FLVContext;
126 |
127 | typedef struct FLVStreamContext {
128 | int64_t last_ts; ///< last timestamp for each stream
129 | } FLVStreamContext;
130 |
131 |
132 | extern int ff_hevc_annexb2mp4_buf(const uint8_t *buf_in, uint8_t **buf_out,
133 | int *size, int filter_ps, int *ps_count);
134 |
135 | extern int ff_isom_write_hvcc(AVIOContext *pb, const uint8_t *data,
136 | int size, int ps_array_completeness);
137 |
138 | static int get_audio_flags(AVFormatContext *s, AVCodecParameters *par)
139 | {
140 | int flags = (par->bits_per_coded_sample == 16) ? FLV_SAMPLESSIZE_16BIT
141 | : FLV_SAMPLESSIZE_8BIT;
142 |
143 | if (par->codec_id == AV_CODEC_ID_AAC) // specs force these parameters
144 | return FLV_CODECID_AAC | FLV_SAMPLERATE_44100HZ |
145 | FLV_SAMPLESSIZE_16BIT | FLV_STEREO;
146 | else if (par->codec_id == AV_CODEC_ID_OPUS) {
147 | return FLV_CODECID_OPUS | FLV_SAMPLERATE_44100HZ |
148 | FLV_SAMPLESSIZE_16BIT | FLV_STEREO;
149 | }
150 | else if (par->codec_id == AV_CODEC_ID_SPEEX) {
151 | if (par->sample_rate != 16000) {
152 | av_log(s, AV_LOG_ERROR,
153 | "FLV only supports wideband (16kHz) Speex audio\n");
154 | return AVERROR(EINVAL);
155 | }
156 | if (par->ch_layout.nb_channels != 1) {
157 | av_log(s, AV_LOG_ERROR, "FLV only supports mono Speex audio\n");
158 | return AVERROR(EINVAL);
159 | }
160 | return FLV_CODECID_SPEEX | FLV_SAMPLERATE_11025HZ | FLV_SAMPLESSIZE_16BIT;
161 | } else {
162 | switch (par->sample_rate) {
163 | case 48000:
164 | // 48khz mp3 is stored with 44k1 samplerate identifer
165 | if (par->codec_id == AV_CODEC_ID_MP3) {
166 | flags |= FLV_SAMPLERATE_44100HZ;
167 | break;
168 | } else {
169 | goto error;
170 | }
171 | case 44100:
172 | flags |= FLV_SAMPLERATE_44100HZ;
173 | break;
174 | case 22050:
175 | flags |= FLV_SAMPLERATE_22050HZ;
176 | break;
177 | case 11025:
178 | flags |= FLV_SAMPLERATE_11025HZ;
179 | break;
180 | case 16000: // nellymoser only
181 | case 8000: // nellymoser only
182 | case 5512: // not MP3
183 | if (par->codec_id != AV_CODEC_ID_MP3) {
184 | flags |= FLV_SAMPLERATE_SPECIAL;
185 | break;
186 | }
187 | default:
188 | error:
189 | av_log(s, AV_LOG_ERROR,
190 | "FLV does not support sample rate %d, "
191 | "choose from (44100, 22050, 11025)\n", par->sample_rate);
192 | return AVERROR(EINVAL);
193 | }
194 | }
195 |
196 | if (par->ch_layout.nb_channels > 1)
197 | flags |= FLV_STEREO;
198 |
199 | switch (par->codec_id) {
200 | case AV_CODEC_ID_MP3:
201 | flags |= FLV_CODECID_MP3 | FLV_SAMPLESSIZE_16BIT;
202 | break;
203 | case AV_CODEC_ID_PCM_U8:
204 | flags |= FLV_CODECID_PCM | FLV_SAMPLESSIZE_8BIT;
205 | break;
206 | case AV_CODEC_ID_PCM_S16BE:
207 | flags |= FLV_CODECID_PCM | FLV_SAMPLESSIZE_16BIT;
208 | break;
209 | case AV_CODEC_ID_PCM_S16LE:
210 | flags |= FLV_CODECID_PCM_LE | FLV_SAMPLESSIZE_16BIT;
211 | break;
212 | case AV_CODEC_ID_ADPCM_SWF:
213 | flags |= FLV_CODECID_ADPCM | FLV_SAMPLESSIZE_16BIT;
214 | break;
215 | case AV_CODEC_ID_NELLYMOSER:
216 | if (par->sample_rate == 8000)
217 | flags |= FLV_CODECID_NELLYMOSER_8KHZ_MONO | FLV_SAMPLESSIZE_16BIT;
218 | else if (par->sample_rate == 16000)
219 | flags |= FLV_CODECID_NELLYMOSER_16KHZ_MONO | FLV_SAMPLESSIZE_16BIT;
220 | else
221 | flags |= FLV_CODECID_NELLYMOSER | FLV_SAMPLESSIZE_16BIT;
222 | break;
223 | case AV_CODEC_ID_PCM_MULAW:
224 | flags = FLV_CODECID_PCM_MULAW | FLV_SAMPLERATE_SPECIAL | FLV_SAMPLESSIZE_16BIT;
225 | break;
226 | case AV_CODEC_ID_PCM_ALAW:
227 | flags = FLV_CODECID_PCM_ALAW | FLV_SAMPLERATE_SPECIAL | FLV_SAMPLESSIZE_16BIT;
228 | break;
229 | case 0:
230 | flags |= par->codec_tag << 4;
231 | break;
232 | default:
233 | av_log(s, AV_LOG_ERROR, "Audio codec '%s' not compatible with FLV\n",
234 | avcodec_get_name(par->codec_id));
235 | return AVERROR(EINVAL);
236 | }
237 |
238 | return flags;
239 | }
240 |
241 | static void put_amf_string(AVIOContext *pb, const char *str)
242 | {
243 | size_t len = strlen(str);
244 | avio_wb16(pb, len);
245 | avio_write(pb, str, len);
246 | }
247 |
248 | // FLV timestamps are 32 bits signed, RTMP timestamps should be 32-bit unsigned
249 | static void put_timestamp(AVIOContext *pb, int64_t ts) {
250 | avio_wb24(pb, ts & 0xFFFFFF);
251 | avio_w8(pb, (ts >> 24) & 0x7F);
252 | }
253 |
254 | static void put_eos_tag(AVIOContext *pb, unsigned ts, enum AVCodecID codec_id)
255 | {
256 | uint32_t tag = ff_codec_get_tag(flv_video_codec_ids, codec_id);
257 | /* ub[4] FrameType = 1, ub[4] CodecId */
258 | tag |= 1 << 4;
259 | avio_w8(pb, FLV_TAG_TYPE_VIDEO);
260 | avio_wb24(pb, 5); /* Tag Data Size */
261 | put_timestamp(pb, ts);
262 | avio_wb24(pb, 0); /* StreamId = 0 */
263 | avio_w8(pb, tag);
264 | avio_w8(pb, 2); /* AVC end of sequence */
265 | avio_wb24(pb, 0); /* Always 0 for AVC EOS. */
266 | avio_wb32(pb, 16); /* Size of FLV tag */
267 | }
268 |
269 | static void put_amf_double(AVIOContext *pb, double d)
270 | {
271 | avio_w8(pb, AMF_DATA_TYPE_NUMBER);
272 | avio_wb64(pb, av_double2int(d));
273 | }
274 |
275 | static void put_amf_byte(AVIOContext *pb, unsigned char abyte)
276 | {
277 | avio_w8(pb, abyte);
278 | }
279 |
280 | static void put_amf_dword_array(AVIOContext *pb, uint32_t dw)
281 | {
282 | avio_w8(pb, AMF_DATA_TYPE_ARRAY);
283 | avio_wb32(pb, dw);
284 | }
285 |
286 | static void put_amf_bool(AVIOContext *pb, int b)
287 | {
288 | avio_w8(pb, AMF_DATA_TYPE_BOOL);
289 | avio_w8(pb, !!b);
290 | }
291 |
292 | static void write_metadata(AVFormatContext *s, unsigned int ts)
293 | {
294 | AVIOContext *pb = s->pb;
295 | FLVContext *flv = s->priv_data;
296 | int write_duration_filesize = !(flv->flags & FLV_NO_DURATION_FILESIZE);
297 | int metadata_count = 0;
298 | int64_t metadata_count_pos;
299 | const AVDictionaryEntry *tag = NULL;
300 |
301 | /* write meta_tag */
302 | avio_w8(pb, FLV_TAG_TYPE_META); // tag type META
303 | flv->metadata_size_pos = avio_tell(pb);
304 | avio_wb24(pb, 0); // size of data part (sum of all parts below)
305 | put_timestamp(pb, ts); // timestamp
306 | avio_wb24(pb, 0); // reserved
307 |
308 | /* now data of data_size size */
309 |
310 | /* first event name as a string */
311 | avio_w8(pb, AMF_DATA_TYPE_STRING);
312 | put_amf_string(pb, "onMetaData"); // 12 bytes
313 |
314 | /* mixed array (hash) with size and string/type/data tuples */
315 | avio_w8(pb, AMF_DATA_TYPE_MIXEDARRAY);
316 | metadata_count_pos = avio_tell(pb);
317 | metadata_count = 4 * !!flv->video_par +
318 | 5 * !!flv->audio_par +
319 | 1 * !!flv->data_par;
320 | if (write_duration_filesize) {
321 | metadata_count += 2; // +2 for duration and file size
322 | }
323 | avio_wb32(pb, metadata_count);
324 |
325 | if (write_duration_filesize) {
326 | put_amf_string(pb, "duration");
327 | flv->duration_offset = avio_tell(pb);
328 | // fill in the guessed duration, it'll be corrected later if incorrect
329 | put_amf_double(pb, s->duration / AV_TIME_BASE);
330 | }
331 |
332 | if (flv->video_par) {
333 | put_amf_string(pb, "width");
334 | put_amf_double(pb, flv->video_par->width);
335 |
336 | put_amf_string(pb, "height");
337 | put_amf_double(pb, flv->video_par->height);
338 |
339 | put_amf_string(pb, "videodatarate");
340 | put_amf_double(pb, flv->video_par->bit_rate / 1024.0);
341 |
342 | if (flv->framerate != 0.0) {
343 | put_amf_string(pb, "framerate");
344 | put_amf_double(pb, flv->framerate);
345 | metadata_count++;
346 | }
347 |
348 | put_amf_string(pb, "videocodecid");
349 | put_amf_double(pb, flv->video_par->codec_tag);
350 | }
351 |
352 | if (flv->audio_par) {
353 | put_amf_string(pb, "audiodatarate");
354 | put_amf_double(pb, flv->audio_par->bit_rate / 1024.0);
355 |
356 | put_amf_string(pb, "audiosamplerate");
357 | put_amf_double(pb, flv->audio_par->sample_rate);
358 |
359 | put_amf_string(pb, "audiosamplesize");
360 | put_amf_double(pb, flv->audio_par->codec_id == AV_CODEC_ID_PCM_U8 ? 8 : 16);
361 |
362 | put_amf_string(pb, "stereo");
363 | put_amf_bool(pb, flv->audio_par->ch_layout.nb_channels == 2);
364 |
365 | put_amf_string(pb, "audiocodecid");
366 | put_amf_double(pb, flv->audio_par->codec_tag);
367 | }
368 |
369 | if (flv->data_par) {
370 | put_amf_string(pb, "datastream");
371 | put_amf_double(pb, 0.0);
372 | }
373 |
374 | ff_standardize_creation_time(s);
375 | while ((tag = av_dict_iterate(s->metadata, tag))) {
376 | if( !strcmp(tag->key, "width")
377 | ||!strcmp(tag->key, "height")
378 | ||!strcmp(tag->key, "videodatarate")
379 | ||!strcmp(tag->key, "framerate")
380 | ||!strcmp(tag->key, "videocodecid")
381 | ||!strcmp(tag->key, "audiodatarate")
382 | ||!strcmp(tag->key, "audiosamplerate")
383 | ||!strcmp(tag->key, "audiosamplesize")
384 | ||!strcmp(tag->key, "stereo")
385 | ||!strcmp(tag->key, "audiocodecid")
386 | ||!strcmp(tag->key, "duration")
387 | ||!strcmp(tag->key, "onMetaData")
388 | ||!strcmp(tag->key, "datasize")
389 | ||!strcmp(tag->key, "lasttimestamp")
390 | ||!strcmp(tag->key, "totalframes")
391 | ||!strcmp(tag->key, "hasAudio")
392 | ||!strcmp(tag->key, "hasVideo")
393 | ||!strcmp(tag->key, "hasCuePoints")
394 | ||!strcmp(tag->key, "hasMetadata")
395 | ||!strcmp(tag->key, "hasKeyframes")
396 | ){
397 | av_log(s, AV_LOG_DEBUG, "Ignoring metadata for %s\n", tag->key);
398 | continue;
399 | }
400 | put_amf_string(pb, tag->key);
401 | avio_w8(pb, AMF_DATA_TYPE_STRING);
402 | put_amf_string(pb, tag->value);
403 | metadata_count++;
404 | }
405 |
406 | if (write_duration_filesize) {
407 | put_amf_string(pb, "filesize");
408 | flv->filesize_offset = avio_tell(pb);
409 | put_amf_double(pb, 0); // delayed write
410 | }
411 |
412 | if (flv->flags & FLV_ADD_KEYFRAME_INDEX) {
413 | flv->keyframe_index_size = 0;
414 |
415 | put_amf_string(pb, "hasVideo");
416 | put_amf_bool(pb, !!flv->video_par);
417 | metadata_count++;
418 |
419 | put_amf_string(pb, "hasKeyframes");
420 | put_amf_bool(pb, 1);
421 | metadata_count++;
422 |
423 | put_amf_string(pb, "hasAudio");
424 | put_amf_bool(pb, !!flv->audio_par);
425 | metadata_count++;
426 |
427 | put_amf_string(pb, "hasMetadata");
428 | put_amf_bool(pb, 1);
429 | metadata_count++;
430 |
431 | put_amf_string(pb, "canSeekToEnd");
432 | put_amf_bool(pb, 1);
433 | metadata_count++;
434 |
435 | put_amf_string(pb, "datasize");
436 | flv->datasize_offset = avio_tell(pb);
437 | flv->datasize = 0;
438 | put_amf_double(pb, flv->datasize);
439 | metadata_count++;
440 |
441 | put_amf_string(pb, "videosize");
442 | flv->videosize_offset = avio_tell(pb);
443 | flv->videosize = 0;
444 | put_amf_double(pb, flv->videosize);
445 | metadata_count++;
446 |
447 | put_amf_string(pb, "audiosize");
448 | flv->audiosize_offset = avio_tell(pb);
449 | flv->audiosize = 0;
450 | put_amf_double(pb, flv->audiosize);
451 | metadata_count++;
452 |
453 | put_amf_string(pb, "lasttimestamp");
454 | flv->lasttimestamp_offset = avio_tell(pb);
455 | flv->lasttimestamp = 0;
456 | put_amf_double(pb, 0);
457 | metadata_count++;
458 |
459 | put_amf_string(pb, "lastkeyframetimestamp");
460 | flv->lastkeyframetimestamp_offset = avio_tell(pb);
461 | flv->lastkeyframetimestamp = 0;
462 | put_amf_double(pb, 0);
463 | metadata_count++;
464 |
465 | put_amf_string(pb, "lastkeyframelocation");
466 | flv->lastkeyframelocation_offset = avio_tell(pb);
467 | flv->lastkeyframelocation = 0;
468 | put_amf_double(pb, 0);
469 | metadata_count++;
470 |
471 | put_amf_string(pb, "keyframes");
472 | put_amf_byte(pb, AMF_DATA_TYPE_OBJECT);
473 | metadata_count++;
474 |
475 | flv->keyframes_info_offset = avio_tell(pb);
476 | }
477 |
478 | put_amf_string(pb, "");
479 | avio_w8(pb, AMF_END_OF_OBJECT);
480 |
481 | /* write total size of tag */
482 | flv->metadata_totalsize = avio_tell(pb) - flv->metadata_size_pos - 10;
483 |
484 | avio_seek(pb, metadata_count_pos, SEEK_SET);
485 | avio_wb32(pb, metadata_count);
486 |
487 | avio_seek(pb, flv->metadata_size_pos, SEEK_SET);
488 | avio_wb24(pb, flv->metadata_totalsize);
489 | avio_skip(pb, flv->metadata_totalsize + 10 - 3);
490 | flv->metadata_totalsize_pos = avio_tell(pb);
491 | avio_wb32(pb, flv->metadata_totalsize + 11);
492 | }
493 |
494 | static int unsupported_codec(AVFormatContext *s,
495 | const char* type, int codec_id)
496 | {
497 | const AVCodecDescriptor *desc = avcodec_descriptor_get(codec_id);
498 | av_log(s, AV_LOG_ERROR,
499 | "%s codec %s not compatible with flv\n",
500 | type,
501 | desc ? desc->name : "unknown");
502 | return AVERROR(ENOSYS);
503 | }
504 |
505 | static int get_codec_fourcc(int codec_id, int* fourcc_int) {
506 | char fourcc[4];
507 |
508 | if (codec_id == AV_CODEC_ID_H265) {
509 | fourcc[0] = 'h';
510 | fourcc[1] = 'v';
511 | fourcc[2] = 'c';
512 | fourcc[3] = '1';
513 | } else if (codec_id == AV_CODEC_ID_AV1) {
514 | fourcc[0] = 'a';
515 | fourcc[1] = 'v';
516 | fourcc[2] = '0';
517 | fourcc[3] = '1';
518 | } else {
519 | return -1;
520 | }
521 |
522 | *fourcc_int = ((int)fourcc[0]) << 24 | ((int)fourcc[1]) << 16
523 | | ((int)fourcc[2]) << 8 | fourcc[3];
524 | return 0;
525 | }
526 |
527 | static int is_flv_extern_header_enable(FLVContext* flv, int codec_id) {
528 | if ((flv->flags & FLV_EXTERN_HEADER) == FLV_EXTERN_HEADER) {
529 | if ((codec_id == AV_CODEC_ID_H265) || (codec_id == AV_CODEC_ID_AV1)) {
530 | return 1;
531 | }
532 | }
533 | return 0;
534 | }
535 |
536 | static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, int64_t ts) {
537 | int64_t data_size;
538 | AVIOContext *pb = s->pb;
539 | FLVContext *flv = s->priv_data;
540 |
541 | if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264
542 | || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC
543 | || par->codec_id == AV_CODEC_ID_OPUS || par->codec_id == AV_CODEC_ID_VP8
544 | || par->codec_id == AV_CODEC_ID_VP9) {
545 | int64_t pos;
546 | avio_w8(pb,
547 | par->codec_type == AVMEDIA_TYPE_VIDEO ?
548 | FLV_TAG_TYPE_VIDEO : FLV_TAG_TYPE_AUDIO);
549 | avio_wb24(pb, 0); // size patched later
550 | put_timestamp(pb, ts);
551 | avio_wb24(pb, 0); // streamid
552 | pos = avio_tell(pb);
553 | if (par->codec_id == AV_CODEC_ID_AAC) {
554 | avio_w8(pb, get_audio_flags(s, par));
555 | avio_w8(pb, 0); // AAC sequence header
556 |
557 | if (!par->extradata_size && (flv->flags & FLV_AAC_SEQ_HEADER_DETECT)) {
558 | PutBitContext pbc;
559 | int samplerate_index;
560 | int channels = flv->audio_par->ch_layout.nb_channels
561 | - (flv->audio_par->ch_layout.nb_channels == 8 ? 1 : 0);
562 | uint8_t data[2];
563 |
564 | for (samplerate_index = 0; samplerate_index < 16;
565 | samplerate_index++)
566 | if (flv->audio_par->sample_rate
567 | == ff_mpeg4audio_sample_rates[samplerate_index])
568 | break;
569 |
570 | init_put_bits(&pbc, data, sizeof(data));
571 | put_bits(&pbc, 5, flv->audio_par->profile + 1); //profile
572 | put_bits(&pbc, 4, samplerate_index); //sample rate index
573 | put_bits(&pbc, 4, channels);
574 | put_bits(&pbc, 1, 0); //frame length - 1024 samples
575 | put_bits(&pbc, 1, 0); //does not depend on core coder
576 | put_bits(&pbc, 1, 0); //is not extension
577 | flush_put_bits(&pbc);
578 |
579 | avio_w8(pb, data[0]);
580 | avio_w8(pb, data[1]);
581 |
582 | av_log(s, AV_LOG_WARNING, "AAC sequence header: %02x %02x.\n",
583 | data[0], data[1]);
584 | }
585 | avio_write(pb, par->extradata, par->extradata_size);
586 | } else if (par->codec_id == AV_CODEC_ID_OPUS) {
587 | avio_w8(pb, get_audio_flags(s, par));
588 | avio_w8(pb, 0); // opus sequence header
589 | avio_write(pb, par->extradata, par->extradata_size);
590 | } else {
591 | if (is_flv_extern_header_enable(flv, par->codec_id)) {
592 | int fourcc_int = 0;
593 |
594 | get_codec_fourcc(par->codec_id, &fourcc_int);
595 | avio_w8(pb, FRAME_HEADER_EX | PACKETTYPE_SEQ_START | FT_KEY); // flags
596 | avio_wb32(pb, fourcc_int);
597 | } else {
598 | avio_w8(pb, par->codec_tag | FLV_FRAME_KEY); // flags
599 | avio_w8(pb, 0); // AVC sequence header
600 | avio_wb24(pb, 0); // composition time
601 | }
602 | if (par->codec_id == AV_CODEC_ID_HEVC) {
603 | ff_isom_write_hvcc(pb, par->extradata, par->extradata_size, 0);
604 | } else if ((par->codec_id == AV_CODEC_ID_VP8) || (par->codec_id == AV_CODEC_ID_VP9)) {
605 | avio_write(pb, par->extradata, par->extradata_size);
606 | } else {
607 | ff_isom_write_avcc(pb, par->extradata, par->extradata_size);
608 | }
609 | }
610 | data_size = avio_tell(pb) - pos;
611 | avio_seek(pb, -data_size - 10, SEEK_CUR);
612 | avio_wb24(pb, data_size);
613 | avio_skip(pb, data_size + 10 - 3);
614 | avio_wb32(pb, data_size + 11); // previous tag size
615 | }
616 | }
617 |
618 | static int flv_append_keyframe_info(AVFormatContext *s, FLVContext *flv, double ts, int64_t pos)
619 | {
620 | FLVFileposition *position = av_malloc(sizeof(FLVFileposition));
621 |
622 | if (!position) {
623 | av_log(s, AV_LOG_WARNING, "no mem for add keyframe index!\n");
624 | return AVERROR(ENOMEM);
625 | }
626 |
627 | position->keyframe_timestamp = ts;
628 | position->keyframe_position = pos;
629 |
630 | if (!flv->filepositions_count) {
631 | flv->filepositions = position;
632 | flv->head_filepositions = flv->filepositions;
633 | position->next = NULL;
634 | } else {
635 | flv->filepositions->next = position;
636 | position->next = NULL;
637 | flv->filepositions = flv->filepositions->next;
638 | }
639 |
640 | flv->filepositions_count++;
641 |
642 | return 0;
643 | }
644 |
645 | static int shift_data(AVFormatContext *s)
646 | {
647 | int ret;
648 | int64_t metadata_size = 0;
649 | FLVContext *flv = s->priv_data;
650 |
651 | metadata_size = flv->filepositions_count * 9 * 2 + 10; /* filepositions and times value */
652 | metadata_size += 2 + 13; /* filepositions String */
653 | metadata_size += 2 + 5; /* times String */
654 | metadata_size += 3; /* Object end */
655 |
656 | flv->keyframe_index_size = metadata_size;
657 |
658 | if (metadata_size < 0)
659 | return metadata_size;
660 |
661 | ret = ff_format_shift_data(s, flv->keyframes_info_offset, metadata_size);
662 | if (ret < 0)
663 | return ret;
664 |
665 | avio_seek(s->pb, flv->metadata_size_pos, SEEK_SET);
666 | avio_wb24(s->pb, flv->metadata_totalsize + metadata_size);
667 |
668 | avio_seek(s->pb, flv->metadata_totalsize_pos + metadata_size, SEEK_SET);
669 | avio_wb32(s->pb, flv->metadata_totalsize + 11 + metadata_size);
670 |
671 | return 0;
672 | }
673 |
674 | static int flv_init(struct AVFormatContext *s)
675 | {
676 | int i;
677 | FLVContext *flv = s->priv_data;
678 |
679 | for (i = 0; i < s->nb_streams; i++) {
680 | AVCodecParameters *par = s->streams[i]->codecpar;
681 | FLVStreamContext *sc;
682 | switch (par->codec_type) {
683 | case AVMEDIA_TYPE_VIDEO:
684 | if (s->streams[i]->avg_frame_rate.den &&
685 | s->streams[i]->avg_frame_rate.num) {
686 | flv->framerate = av_q2d(s->streams[i]->avg_frame_rate);
687 | }
688 | if (flv->video_par) {
689 | av_log(s, AV_LOG_ERROR,
690 | "at most one video stream is supported in flv\n");
691 | return AVERROR(EINVAL);
692 | }
693 | flv->video_par = par;
694 | if (!ff_codec_get_tag(flv_video_codec_ids, par->codec_id))
695 | return unsupported_codec(s, "Video", par->codec_id);
696 |
697 | if (par->codec_id == AV_CODEC_ID_MPEG4 ||
698 | par->codec_id == AV_CODEC_ID_H263) {
699 | int error = s->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL;
700 | av_log(s, error ? AV_LOG_ERROR : AV_LOG_WARNING,
701 | "Codec %s is not supported in the official FLV specification,\n", avcodec_get_name(par->codec_id));
702 |
703 | if (error) {
704 | av_log(s, AV_LOG_ERROR,
705 | "use vstrict=-1 / -strict -1 to use it anyway.\n");
706 | return AVERROR(EINVAL);
707 | }
708 | } else if (par->codec_id == AV_CODEC_ID_VP6) {
709 | av_log(s, AV_LOG_WARNING,
710 | "Muxing VP6 in flv will produce flipped video on playback.\n");
711 | }
712 | break;
713 | case AVMEDIA_TYPE_AUDIO:
714 | if (flv->audio_par) {
715 | av_log(s, AV_LOG_ERROR,
716 | "at most one audio stream is supported in flv\n");
717 | return AVERROR(EINVAL);
718 | }
719 | flv->audio_par = par;
720 | if (get_audio_flags(s, par) < 0)
721 | return unsupported_codec(s, "Audio", par->codec_id);
722 | if (par->codec_id == AV_CODEC_ID_PCM_S16BE)
723 | av_log(s, AV_LOG_WARNING,
724 | "16-bit big-endian audio in flv is valid but most likely unplayable (hardware dependent); use s16le\n");
725 | break;
726 | case AVMEDIA_TYPE_DATA:
727 | if (par->codec_id != AV_CODEC_ID_TEXT && par->codec_id != AV_CODEC_ID_NONE)
728 | return unsupported_codec(s, "Data", par->codec_id);
729 | flv->data_par = par;
730 | break;
731 | case AVMEDIA_TYPE_SUBTITLE:
732 | if (par->codec_id != AV_CODEC_ID_TEXT) {
733 | av_log(s, AV_LOG_ERROR, "Subtitle codec '%s' for stream %d is not compatible with FLV\n",
734 | avcodec_get_name(par->codec_id), i);
735 | return AVERROR_INVALIDDATA;
736 | }
737 | flv->data_par = par;
738 | break;
739 | default:
740 | av_log(s, AV_LOG_ERROR, "Codec type '%s' for stream %d is not compatible with FLV\n",
741 | av_get_media_type_string(par->codec_type), i);
742 | return AVERROR(EINVAL);
743 | }
744 | avpriv_set_pts_info(s->streams[i], 32, 1, 1000); /* 32 bit pts in ms */
745 |
746 | sc = av_mallocz(sizeof(FLVStreamContext));
747 | if (!sc)
748 | return AVERROR(ENOMEM);
749 | s->streams[i]->priv_data = sc;
750 | sc->last_ts = -1;
751 | }
752 |
753 | flv->delay = AV_NOPTS_VALUE;
754 |
755 | return 0;
756 | }
757 |
758 | static int flv_write_header(AVFormatContext *s)
759 | {
760 | int i;
761 | AVIOContext *pb = s->pb;
762 | FLVContext *flv = s->priv_data;
763 |
764 | avio_write(pb, "FLV", 3);
765 | avio_w8(pb, 1);
766 | avio_w8(pb, FLV_HEADER_FLAG_HASAUDIO * !!flv->audio_par +
767 | FLV_HEADER_FLAG_HASVIDEO * !!flv->video_par);
768 | avio_wb32(pb, 9);
769 | avio_wb32(pb, 0);
770 |
771 | for (i = 0; i < s->nb_streams; i++)
772 | if (s->streams[i]->codecpar->codec_tag == 5) {
773 | avio_w8(pb, 8); // message type
774 | avio_wb24(pb, 0); // include flags
775 | avio_wb24(pb, 0); // time stamp
776 | avio_wb32(pb, 0); // reserved
777 | avio_wb32(pb, 11); // size
778 | flv->reserved = 5;
779 | }
780 |
781 | if (flv->flags & FLV_NO_METADATA) {
782 | pb->seekable = 0;
783 | } else {
784 | write_metadata(s, 0);
785 | }
786 |
787 | for (i = 0; i < s->nb_streams; i++) {
788 | flv_write_codec_header(s, s->streams[i]->codecpar, 0);
789 | }
790 |
791 | flv->datastart_offset = avio_tell(pb);
792 | return 0;
793 | }
794 |
795 | static int flv_write_trailer(AVFormatContext *s)
796 | {
797 | int64_t file_size;
798 | AVIOContext *pb = s->pb;
799 | FLVContext *flv = s->priv_data;
800 | int build_keyframes_idx = flv->flags & FLV_ADD_KEYFRAME_INDEX;
801 | int i, res;
802 | int64_t cur_pos = avio_tell(s->pb);
803 |
804 | if (build_keyframes_idx) {
805 | const FLVFileposition *newflv_posinfo;
806 |
807 | avio_seek(pb, flv->videosize_offset, SEEK_SET);
808 | put_amf_double(pb, flv->videosize);
809 |
810 | avio_seek(pb, flv->audiosize_offset, SEEK_SET);
811 | put_amf_double(pb, flv->audiosize);
812 |
813 | avio_seek(pb, flv->lasttimestamp_offset, SEEK_SET);
814 | put_amf_double(pb, flv->lasttimestamp);
815 |
816 | avio_seek(pb, flv->lastkeyframetimestamp_offset, SEEK_SET);
817 | put_amf_double(pb, flv->lastkeyframetimestamp);
818 |
819 | avio_seek(pb, flv->lastkeyframelocation_offset, SEEK_SET);
820 | put_amf_double(pb, flv->lastkeyframelocation + flv->keyframe_index_size);
821 | avio_seek(pb, cur_pos, SEEK_SET);
822 |
823 | res = shift_data(s);
824 | if (res < 0) {
825 | goto end;
826 | }
827 | avio_seek(pb, flv->keyframes_info_offset, SEEK_SET);
828 | put_amf_string(pb, "filepositions");
829 | put_amf_dword_array(pb, flv->filepositions_count);
830 | for (newflv_posinfo = flv->head_filepositions; newflv_posinfo; newflv_posinfo = newflv_posinfo->next) {
831 | put_amf_double(pb, newflv_posinfo->keyframe_position + flv->keyframe_index_size);
832 | }
833 |
834 | put_amf_string(pb, "times");
835 | put_amf_dword_array(pb, flv->filepositions_count);
836 | for (newflv_posinfo = flv->head_filepositions; newflv_posinfo; newflv_posinfo = newflv_posinfo->next) {
837 | put_amf_double(pb, newflv_posinfo->keyframe_timestamp);
838 | }
839 |
840 | put_amf_string(pb, "");
841 | avio_w8(pb, AMF_END_OF_OBJECT);
842 |
843 | avio_seek(pb, cur_pos + flv->keyframe_index_size, SEEK_SET);
844 | }
845 |
846 | end:
847 | if (flv->flags & FLV_NO_SEQUENCE_END) {
848 | av_log(s, AV_LOG_DEBUG, "FLV no sequence end mode open\n");
849 | } else {
850 | /* Add EOS tag */
851 | for (i = 0; i < s->nb_streams; i++) {
852 | AVCodecParameters *par = s->streams[i]->codecpar;
853 | FLVStreamContext *sc = s->streams[i]->priv_data;
854 |
855 | if (is_flv_extern_header_enable(flv, par->codec_id)) {
856 | int fourcc_int = 0;
857 |
858 | get_codec_fourcc(par->codec_id, &fourcc_int);
859 | avio_w8(pb, FRAME_HEADER_EX | PACKETTYPE_SEQ_END); // flags
860 | avio_wb32(pb, fourcc_int);
861 | } else {
862 | if (par->codec_type == AVMEDIA_TYPE_VIDEO &&
863 | (par->codec_id == AV_CODEC_ID_H265 || par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4))
864 | put_eos_tag(pb, sc->last_ts, par->codec_id);
865 | }
866 | }
867 | }
868 |
869 | file_size = avio_tell(pb);
870 |
871 | if (build_keyframes_idx) {
872 | flv->datasize = file_size - flv->datastart_offset;
873 | avio_seek(pb, flv->datasize_offset, SEEK_SET);
874 | put_amf_double(pb, flv->datasize);
875 | }
876 | if (!(flv->flags & FLV_NO_METADATA)) {
877 | if (!(flv->flags & FLV_NO_DURATION_FILESIZE)) {
878 | /* update information */
879 | if (avio_seek(pb, flv->duration_offset, SEEK_SET) < 0) {
880 | av_log(s, AV_LOG_WARNING, "Failed to update header with correct duration.\n");
881 | } else {
882 | put_amf_double(pb, flv->duration / (double)1000);
883 | }
884 | if (avio_seek(pb, flv->filesize_offset, SEEK_SET) < 0) {
885 | av_log(s, AV_LOG_WARNING, "Failed to update header with correct filesize.\n");
886 | } else {
887 | put_amf_double(pb, file_size);
888 | }
889 | }
890 | }
891 |
892 | return 0;
893 | }
894 |
895 | static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
896 | {
897 | AVIOContext *pb = s->pb;
898 | AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar;
899 | FLVContext *flv = s->priv_data;
900 | FLVStreamContext *sc = s->streams[pkt->stream_index]->priv_data;
901 | unsigned ts;
902 | int size = pkt->size;
903 | uint8_t *data = NULL;
904 | int flags = -1, flags_size, ret = 0;
905 | int64_t cur_offset = avio_tell(pb);
906 |
907 | if (par->codec_type == AVMEDIA_TYPE_AUDIO && !pkt->size) {
908 | av_log(s, AV_LOG_WARNING, "Empty audio Packet\n");
909 | return AVERROR(EINVAL);
910 | }
911 |
912 | if (par->codec_id == AV_CODEC_ID_VP6F || par->codec_id == AV_CODEC_ID_VP6A ||
913 | par->codec_id == AV_CODEC_ID_VP6 || par->codec_id == AV_CODEC_ID_AAC ||
914 | par->codec_id == AV_CODEC_ID_OPUS)
915 | flags_size = 2;
916 | else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4 ||
917 | par->codec_id == AV_CODEC_ID_H265 || par->codec_id == AV_CODEC_ID_VP8 ||
918 | par->codec_id == AV_CODEC_ID_VP9) {
919 | if (is_flv_extern_header_enable(flv, par->codec_id) && (pkt->dts != pkt->pts)) {
920 | flags_size = 8;
921 | } else {
922 | flags_size = 5;
923 | }
924 | }
925 | else
926 | flags_size = 1;
927 |
928 | if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264
929 | || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC
930 | || par->codec_id == AV_CODEC_ID_VP8 || par->codec_id == AV_CODEC_ID_VP9
931 | || par->codec_id == AV_CODEC_ID_OPUS) {
932 | size_t side_size;
933 | uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size);
934 | if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) {
935 | ret = ff_alloc_extradata(par, side_size);
936 | if (ret < 0)
937 | return ret;
938 | memcpy(par->extradata, side, side_size);
939 | flv_write_codec_header(s, par, pkt->dts);
940 | }
941 | }
942 |
943 |
944 | if (flv->delay == AV_NOPTS_VALUE)
945 | flv->delay = -pkt->dts;
946 |
947 | if (pkt->dts < -flv->delay) {
948 | av_log(s, AV_LOG_WARNING,
949 | "Packets are not in the proper order with respect to DTS\n");
950 | return AVERROR(EINVAL);
951 | }
952 | if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4
953 | || par->codec_id == AV_CODEC_ID_H265 || par->codec_id == AV_CODEC_ID_VP8
954 | || par->codec_id == AV_CODEC_ID_VP9) {
955 | if (pkt->pts == AV_NOPTS_VALUE) {
956 | av_log(s, AV_LOG_ERROR, "Packet is missing PTS\n");
957 | return AVERROR(EINVAL);
958 | }
959 | }
960 |
961 | ts = pkt->dts;
962 |
963 | if (s->event_flags & AVSTREAM_EVENT_FLAG_METADATA_UPDATED) {
964 | write_metadata(s, ts);
965 | s->event_flags &= ~AVSTREAM_EVENT_FLAG_METADATA_UPDATED;
966 | }
967 |
968 | avio_write_marker(pb, av_rescale(ts, AV_TIME_BASE, 1000),
969 | pkt->flags & AV_PKT_FLAG_KEY && (flv->video_par ? par->codec_type == AVMEDIA_TYPE_VIDEO : 1) ? AVIO_DATA_MARKER_SYNC_POINT : AVIO_DATA_MARKER_BOUNDARY_POINT);
970 |
971 | switch (par->codec_type) {
972 | case AVMEDIA_TYPE_VIDEO:
973 | avio_w8(pb, FLV_TAG_TYPE_VIDEO);
974 |
975 | flags = ff_codec_get_tag(flv_video_codec_ids, par->codec_id);
976 |
977 | flags |= pkt->flags & AV_PKT_FLAG_KEY ? FLV_FRAME_KEY : FLV_FRAME_INTER;
978 | break;
979 | case AVMEDIA_TYPE_AUDIO:
980 | flags = get_audio_flags(s, par);
981 |
982 | av_assert0(size);
983 |
984 | avio_w8(pb, FLV_TAG_TYPE_AUDIO);
985 | break;
986 | case AVMEDIA_TYPE_SUBTITLE:
987 | case AVMEDIA_TYPE_DATA:
988 | avio_w8(pb, FLV_TAG_TYPE_META);
989 | break;
990 | default:
991 | return AVERROR(EINVAL);
992 | }
993 |
994 | if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) {
995 | /* check if extradata looks like mp4 formatted */
996 | if (par->extradata_size > 0 && *(uint8_t*)par->extradata != 1)
997 | if ((ret = ff_avc_parse_nal_units_buf(pkt->data, &data, &size)) < 0)
998 | return ret;
999 | }
1000 | else if (par->codec_id == AV_CODEC_ID_HEVC) {
1001 | if (par->extradata_size > 0 && *(uint8_t*)par->extradata != 1) {
1002 | if ((ret = ff_hevc_annexb2mp4_buf(pkt->data, &data, &size, (int)0, (int*)NULL)) < 0)
1003 | return ret;
1004 | }
1005 | } else if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&
1006 | (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {
1007 | if (!s->streams[pkt->stream_index]->nb_frames) {
1008 | av_log(s, AV_LOG_ERROR, "Malformed AAC bitstream detected: "
1009 | "use the audio bitstream filter 'aac_adtstoasc' to fix it "
1010 | "('-bsf:a aac_adtstoasc' option with ffmpeg)\n");
1011 | return AVERROR_INVALIDDATA;
1012 | }
1013 | av_log(s, AV_LOG_WARNING, "aac bitstream error\n");
1014 | }
1015 |
1016 | /* check Speex packet duration */
1017 | if (par->codec_id == AV_CODEC_ID_SPEEX && ts - sc->last_ts > 160)
1018 | av_log(s, AV_LOG_WARNING, "Warning: Speex stream has more than "
1019 | "8 frames per packet. Adobe Flash "
1020 | "Player cannot handle this!\n");
1021 |
1022 | if (sc->last_ts < ts)
1023 | sc->last_ts = ts;
1024 |
1025 | if (size + flags_size >= 1<<24) {
1026 | av_log(s, AV_LOG_ERROR, "Too large packet with size %u >= %u\n",
1027 | size + flags_size, 1<<24);
1028 | ret = AVERROR(EINVAL);
1029 | goto fail;
1030 | }
1031 |
1032 | avio_wb24(pb, size + flags_size);
1033 | put_timestamp(pb, ts);
1034 | avio_wb24(pb, flv->reserved);
1035 |
1036 | if (par->codec_type == AVMEDIA_TYPE_DATA ||
1037 | par->codec_type == AVMEDIA_TYPE_SUBTITLE ) {
1038 | int data_size;
1039 | int64_t metadata_size_pos = avio_tell(pb);
1040 | if (par->codec_id == AV_CODEC_ID_TEXT) {
1041 | // legacy FFmpeg magic?
1042 | avio_w8(pb, AMF_DATA_TYPE_STRING);
1043 | put_amf_string(pb, "onTextData");
1044 | avio_w8(pb, AMF_DATA_TYPE_MIXEDARRAY);
1045 | avio_wb32(pb, 2);
1046 | put_amf_string(pb, "type");
1047 | avio_w8(pb, AMF_DATA_TYPE_STRING);
1048 | put_amf_string(pb, "Text");
1049 | put_amf_string(pb, "text");
1050 | avio_w8(pb, AMF_DATA_TYPE_STRING);
1051 | put_amf_string(pb, pkt->data);
1052 | put_amf_string(pb, "");
1053 | avio_w8(pb, AMF_END_OF_OBJECT);
1054 | } else {
1055 | // just pass the metadata through
1056 | avio_write(pb, data ? data : pkt->data, size);
1057 | }
1058 | /* write total size of tag */
1059 | data_size = avio_tell(pb) - metadata_size_pos;
1060 | avio_seek(pb, metadata_size_pos - 10, SEEK_SET);
1061 | avio_wb24(pb, data_size);
1062 | avio_seek(pb, data_size + 10 - 3, SEEK_CUR);
1063 | avio_wb32(pb, data_size + 11);
1064 | } else {
1065 | if (!is_flv_extern_header_enable(flv, par->codec_id)) {
1066 | av_assert1(flags>=0);
1067 | avio_w8(pb,flags);
1068 | }
1069 | if (par->codec_id == AV_CODEC_ID_VP6)
1070 | avio_w8(pb,0);
1071 | if (par->codec_id == AV_CODEC_ID_VP6F || par->codec_id == AV_CODEC_ID_VP6A) {
1072 | if (par->extradata_size)
1073 | avio_w8(pb, par->extradata[0]);
1074 | else
1075 | avio_w8(pb, ((FFALIGN(par->width, 16) - par->width) << 4) |
1076 | (FFALIGN(par->height, 16) - par->height));
1077 | } else if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_OPUS) {
1078 | avio_w8(pb, 1); // AAC raw
1079 | } else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4
1080 | || par->codec_id == AV_CODEC_ID_HEVC || par->codec_id == AV_CODEC_ID_VP8
1081 | || par->codec_id == AV_CODEC_ID_VP9 || par->codec_id == AV_CODEC_ID_AV1) {
1082 | if (is_flv_extern_header_enable(flv, par->codec_id)) {
1083 | int fourcc_int = 0;
1084 | int ext_type = PACKETTYPE_FRAMES;
1085 | unsigned char is_key = (pkt->flags & AV_PKT_FLAG_KEY) ? FT_KEY : 0;
1086 | unsigned char type = FRAME_HEADER_EX;
1087 |
1088 | if (pkt->dts == pkt->pts) {
1089 | ext_type = PACKETTYPE_FRAMESX;
1090 | }
1091 | type |= ext_type | is_key;
1092 | get_codec_fourcc(par->codec_id, &fourcc_int);
1093 | avio_w8(pb, type);
1094 | avio_wb32(pb, fourcc_int);
1095 | if (ext_type == PACKETTYPE_FRAMES) {
1096 | avio_wb24(pb, pkt->pts - pkt->dts);
1097 | }
1098 | } else {
1099 | avio_w8(pb, 1); // AVC NALU
1100 | avio_wb24(pb, pkt->pts - pkt->dts);
1101 | }
1102 | }
1103 |
1104 | avio_write(pb, data ? data : pkt->data, size);
1105 |
1106 | avio_wb32(pb, size + flags_size + 11); // previous tag size
1107 | flv->duration = FFMAX(flv->duration,
1108 | pkt->pts + flv->delay + pkt->duration);
1109 | }
1110 |
1111 | if (flv->flags & FLV_ADD_KEYFRAME_INDEX) {
1112 | switch (par->codec_type) {
1113 | case AVMEDIA_TYPE_VIDEO:
1114 | flv->videosize += (avio_tell(pb) - cur_offset);
1115 | flv->lasttimestamp = pkt->dts / 1000.0;
1116 | if (pkt->flags & AV_PKT_FLAG_KEY) {
1117 | flv->lastkeyframetimestamp = flv->lasttimestamp;
1118 | flv->lastkeyframelocation = cur_offset;
1119 | ret = flv_append_keyframe_info(s, flv, flv->lasttimestamp, cur_offset);
1120 | if (ret < 0)
1121 | goto fail;
1122 | }
1123 | break;
1124 |
1125 | case AVMEDIA_TYPE_AUDIO:
1126 | flv->audiosize += (avio_tell(pb) - cur_offset);
1127 | break;
1128 |
1129 | default:
1130 | av_log(s, AV_LOG_WARNING, "par->codec_type is type = [%d]\n", par->codec_type);
1131 | break;
1132 | }
1133 | }
1134 | fail:
1135 | av_free(data);
1136 |
1137 | return ret;
1138 | }
1139 |
1140 | static int flv_check_bitstream(AVFormatContext *s, AVStream *st,
1141 | const AVPacket *pkt)
1142 | {
1143 | int ret = 1;
1144 |
1145 | if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
1146 | if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0)
1147 | ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL);
1148 | }
1149 | return ret;
1150 | }
1151 |
1152 | static void flv_deinit(AVFormatContext *s)
1153 | {
1154 | FLVContext *flv = s->priv_data;
1155 | FLVFileposition *filepos = flv->head_filepositions;
1156 |
1157 | while (filepos) {
1158 | FLVFileposition *next = filepos->next;
1159 | av_free(filepos);
1160 | filepos = next;
1161 | }
1162 | flv->filepositions = flv->head_filepositions = NULL;
1163 | flv->filepositions_count = 0;
1164 | }
1165 |
1166 | static const AVOption options[] = {
1167 | { "flvflags", "FLV muxer flags", offsetof(FLVContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" },
1168 | { "aac_seq_header_detect", "Put AAC sequence header based on stream data", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_AAC_SEQ_HEADER_DETECT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" },
1169 | { "no_sequence_end", "disable sequence end for FLV", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_NO_SEQUENCE_END}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" },
1170 | { "no_metadata", "disable metadata for FLV", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_NO_METADATA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" },
1171 | { "no_duration_filesize", "disable duration and filesize zero value metadata for FLV", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_NO_DURATION_FILESIZE}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" },
1172 | { "add_keyframe_index", "Add keyframe index metadata", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_ADD_KEYFRAME_INDEX}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" },
1173 | { "ext_header", "enable extern header", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_EXTERN_HEADER}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" },
1174 | { NULL },
1175 | };
1176 |
1177 | static const AVClass flv_muxer_class = {
1178 | .class_name = "flv muxer",
1179 | .item_name = av_default_item_name,
1180 | .option = options,
1181 | .version = LIBAVUTIL_VERSION_INT,
1182 | };
1183 |
1184 | const FFOutputFormat ff_flv_muxer = {
1185 | .p.name = "flv",
1186 | .p.long_name = NULL_IF_CONFIG_SMALL("FLV (Flash Video)"),
1187 | .p.mime_type = "video/x-flv",
1188 | .p.extensions = "flv",
1189 | .priv_data_size = sizeof(FLVContext),
1190 | .p.audio_codec = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_ADPCM_SWF,
1191 | .p.video_codec = AV_CODEC_ID_FLV1,
1192 | .init = flv_init,
1193 | .write_header = flv_write_header,
1194 | .write_packet = flv_write_packet,
1195 | .write_trailer = flv_write_trailer,
1196 | .deinit = flv_deinit,
1197 | .check_bitstream= flv_check_bitstream,
1198 | .p.codec_tag = (const AVCodecTag* const []) {
1199 | flv_video_codec_ids, flv_audio_codec_ids, 0
1200 | },
1201 | .p.flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS |
1202 | AVFMT_TS_NONSTRICT,
1203 | .p.priv_class = &flv_muxer_class,
1204 | };
1205 |
--------------------------------------------------------------------------------