├── 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 | --------------------------------------------------------------------------------