1958 lines · 68.8 KB · C
RawDownload
/* * FLV demuxer * Copyright (c) 2003 The FFmpeg Project * * This demuxer will generate a 1 byte extradata for VP6F content. * It is composed of: *  - upper 4 bits: difference between encoded width and visible width *  - lower 4 bits: difference between encoded height and visible height * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libavutil/avassert.h"#include "libavutil/avstring.h"#include "libavutil/channel_layout.h"#include "libavutil/dict.h"#include "libavutil/dict_internal.h"#include "libavutil/mem.h"#include "libavutil/opt.h"#include "libavutil/internal.h"#include "libavutil/intfloat.h"#include "libavutil/intreadwrite.h"#include "libavutil/mastering_display_metadata.h"#include "avformat.h"#include "demux.h"#include "internal.h"#include "flv.h" #define VALIDATE_INDEX_TS_THRESH 2500 #define RESYNC_BUFFER_SIZE (1<<20) #define MAX_DEPTH 16      ///< arbitrary limit to prevent unbounded recursion typedef struct FLVMasteringMeta {    double r_x;    double r_y;    double g_x;    double g_y;    double b_x;    double b_y;    double white_x;    double white_y;    double max_luminance;    double min_luminance;} FLVMasteringMeta; typedef struct FLVMetaVideoColor {    uint64_t matrix_coefficients;    uint64_t transfer_characteristics;    uint64_t primaries;    uint64_t max_cll;    uint64_t max_fall;    FLVMasteringMeta mastering_meta;} FLVMetaVideoColor; typedef struct FLVContext {    const AVClass *class; ///< Class for private options.    int trust_metadata;   ///< configure streams according onMetaData    int trust_datasize;   ///< trust data size of FLVTag    int dump_full_metadata;   ///< Dump full metadata of the onMetadata    int wrong_dts;        ///< wrong dts due to negative cts    uint8_t *new_extradata[FLV_STREAM_TYPE_NB];    int new_extradata_size[FLV_STREAM_TYPE_NB];    int last_sample_rate;    int last_channels;    struct {        int64_t dts;        int64_t pos;    } validate_index[2];    int validate_next;    int validate_count;    int searched_for_end;     uint8_t resync_buffer[2*RESYNC_BUFFER_SIZE];     int broken_sizes;    int64_t sum_flv_tag_size;     int last_keyframe_stream_index;    int keyframe_count;    int64_t video_bit_rate;    int64_t audio_bit_rate;    int64_t *keyframe_times;    int64_t *keyframe_filepositions;    AVRational framerate;    int64_t last_ts;    int64_t time_offset;    int64_t time_pos;     FLVMetaVideoColor *metaVideoColor;    int meta_color_info_flag;     uint8_t **mt_extradata;    int *mt_extradata_sz;    int mt_extradata_cnt;} FLVContext; /* AMF date type */typedef struct amf_date {    double   milliseconds;    int16_t  timezone;} amf_date; static int probe(const AVProbeData *p, int live){    const uint8_t *d = p->buf;    unsigned offset = AV_RB32(d + 5);     if (d[0] == 'F' &&        d[1] == 'L' &&        d[2] == 'V' &&        d[3] < 5 && d[5] == 0 &&        offset + 100 < p->buf_size &&        offset > 8) {        int is_live = !memcmp(d + offset + 40, "NGINX RTMP", 10);         if (live == is_live)            return AVPROBE_SCORE_MAX;    }    return 0;} static int flv_probe(const AVProbeData *p){    return probe(p, 0);} static int live_flv_probe(const AVProbeData *p){    return probe(p, 1);} static int kux_probe(const AVProbeData *p){    const uint8_t *d = p->buf;     if (d[0] == 'K' &&        d[1] == 'D' &&        d[2] == 'K' &&        d[3] == 0 &&        d[4] == 0) {        return AVPROBE_SCORE_EXTENSION + 1;    }    return 0;} static void add_keyframes_index(AVFormatContext *s){    FLVContext *flv   = s->priv_data;    AVStream *stream  = NULL;    unsigned int i    = 0;     if (flv->last_keyframe_stream_index < 0) {        av_log(s, AV_LOG_DEBUG, "keyframe stream hasn't been created\n");        return;    }     av_assert0(flv->last_keyframe_stream_index <= s->nb_streams);    stream = s->streams[flv->last_keyframe_stream_index];     if (ffstream(stream)->nb_index_entries == 0) {        for (i = 0; i < flv->keyframe_count; i++) {            av_log(s, AV_LOG_TRACE, "keyframe filepositions = %"PRId64" times = %"PRId64"\n",                   flv->keyframe_filepositions[i], flv->keyframe_times[i]);            av_add_index_entry(stream, flv->keyframe_filepositions[i],                flv->keyframe_times[i], 0, 0, AVINDEX_KEYFRAME);        }    } else        av_log(s, AV_LOG_WARNING, "Skipping duplicate index\n");     if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {        av_freep(&flv->keyframe_times);        av_freep(&flv->keyframe_filepositions);        flv->keyframe_count = 0;    }} static AVStream *create_stream(AVFormatContext *s, int codec_type, int track_idx){    FFFormatContext *const si = ffformatcontext(s);    FLVContext *flv   = s->priv_data;    AVStream *st = avformat_new_stream(s, NULL);    if (!st)        return NULL;    st->codecpar->codec_type = codec_type;    st->id = track_idx;    avpriv_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */    if (track_idx)        return st;     if (s->nb_streams>=3 ||(   s->nb_streams==2                           && s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE                           && s->streams[1]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE                           && s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_DATA                           && s->streams[1]->codecpar->codec_type != AVMEDIA_TYPE_DATA))        s->ctx_flags &= ~AVFMTCTX_NOHEADER;    if (codec_type == AVMEDIA_TYPE_AUDIO) {        st->codecpar->bit_rate = flv->audio_bit_rate;        si->missing_streams &= ~FLV_HEADER_FLAG_HASAUDIO;    }    if (codec_type == AVMEDIA_TYPE_VIDEO) {        st->codecpar->bit_rate = flv->video_bit_rate;        si->missing_streams &= ~FLV_HEADER_FLAG_HASVIDEO;        st->avg_frame_rate = flv->framerate;    }     flv->last_keyframe_stream_index = s->nb_streams - 1;    add_keyframes_index(s);    return st;} static int flv_same_audio_codec(AVCodecParameters *apar, int flags, uint32_t codec_fourcc){    int bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8;    int flv_codecid           = flags & FLV_AUDIO_CODECID_MASK;    int codec_id;     switch (codec_fourcc) {    case MKBETAG('m', 'p', '4', 'a'):        return apar->codec_id == AV_CODEC_ID_AAC;    case MKBETAG('O', 'p', 'u', 's'):        return apar->codec_id == AV_CODEC_ID_OPUS;    case MKBETAG('.', 'm', 'p', '3'):        return apar->codec_id == AV_CODEC_ID_MP3;    case MKBETAG('f', 'L', 'a', 'C'):        return apar->codec_id == AV_CODEC_ID_FLAC;    case MKBETAG('a', 'c', '-', '3'):        return apar->codec_id == AV_CODEC_ID_AC3;    case MKBETAG('e', 'c', '-', '3'):        return apar->codec_id == AV_CODEC_ID_EAC3;    case 0:        // Not enhanced flv, continue as normal.        break;    default:        // Unknown FOURCC        return 0;    }     if (!apar->codec_id && !apar->codec_tag)        return 1;     if (apar->bits_per_coded_sample != bits_per_coded_sample)        return 0;     switch (flv_codecid) {    // no distinction between S16 and S8 PCM codec flags    case FLV_CODECID_PCM:        codec_id = bits_per_coded_sample == 8                   ? AV_CODEC_ID_PCM_U8#if HAVE_BIGENDIAN                   : AV_CODEC_ID_PCM_S16BE;#else                   : AV_CODEC_ID_PCM_S16LE;#endif        return codec_id == apar->codec_id;    case FLV_CODECID_PCM_LE:        codec_id = bits_per_coded_sample == 8                   ? AV_CODEC_ID_PCM_U8                   : AV_CODEC_ID_PCM_S16LE;        return codec_id == apar->codec_id;    case FLV_CODECID_AAC:        return apar->codec_id == AV_CODEC_ID_AAC;    case FLV_CODECID_ADPCM:        return apar->codec_id == AV_CODEC_ID_ADPCM_SWF;    case FLV_CODECID_SPEEX:        return apar->codec_id == AV_CODEC_ID_SPEEX;    case FLV_CODECID_MP3:        return apar->codec_id == AV_CODEC_ID_MP3;    case FLV_CODECID_NELLYMOSER_8KHZ_MONO:    case FLV_CODECID_NELLYMOSER_16KHZ_MONO:    case FLV_CODECID_NELLYMOSER:        return apar->codec_id == AV_CODEC_ID_NELLYMOSER;    case FLV_CODECID_PCM_MULAW:        return apar->sample_rate == 8000 &&               apar->codec_id    == AV_CODEC_ID_PCM_MULAW;    case FLV_CODECID_PCM_ALAW:        return apar->sample_rate == 8000 &&               apar->codec_id    == AV_CODEC_ID_PCM_ALAW;    default:        return apar->codec_tag == (flv_codecid >> FLV_AUDIO_CODECID_OFFSET);    }} static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream,                                AVCodecParameters *apar, int flv_codecid){    switch (flv_codecid) {    // no distinction between S16 and S8 PCM codec flags    case FLV_CODECID_PCM:        apar->codec_id = apar->bits_per_coded_sample == 8                           ? AV_CODEC_ID_PCM_U8#if HAVE_BIGENDIAN                           : AV_CODEC_ID_PCM_S16BE;#else                           : AV_CODEC_ID_PCM_S16LE;#endif        break;    case FLV_CODECID_PCM_LE:        apar->codec_id = apar->bits_per_coded_sample == 8                           ? AV_CODEC_ID_PCM_U8                           : AV_CODEC_ID_PCM_S16LE;        break;    case FLV_CODECID_AAC:        apar->codec_id = AV_CODEC_ID_AAC;        break;    case FLV_CODECID_ADPCM:        apar->codec_id = AV_CODEC_ID_ADPCM_SWF;        break;    case FLV_CODECID_SPEEX:        apar->codec_id    = AV_CODEC_ID_SPEEX;        apar->sample_rate = 16000;        break;    case FLV_CODECID_MP3:        apar->codec_id      = AV_CODEC_ID_MP3;        ffstream(astream)->need_parsing = AVSTREAM_PARSE_FULL;        break;    case FLV_CODECID_NELLYMOSER_8KHZ_MONO:        // in case metadata does not otherwise declare samplerate        apar->sample_rate = 8000;        apar->codec_id    = AV_CODEC_ID_NELLYMOSER;        break;    case FLV_CODECID_NELLYMOSER_16KHZ_MONO:        apar->sample_rate = 16000;        apar->codec_id    = AV_CODEC_ID_NELLYMOSER;        break;    case FLV_CODECID_NELLYMOSER:        apar->codec_id = AV_CODEC_ID_NELLYMOSER;        break;    case FLV_CODECID_PCM_MULAW:        apar->sample_rate = 8000;        apar->codec_id    = AV_CODEC_ID_PCM_MULAW;        break;    case FLV_CODECID_PCM_ALAW:        apar->sample_rate = 8000;        apar->codec_id    = AV_CODEC_ID_PCM_ALAW;        break;    case MKBETAG('m', 'p', '4', 'a'):        apar->codec_id = AV_CODEC_ID_AAC;        return;    case MKBETAG('O', 'p', 'u', 's'):        apar->codec_id = AV_CODEC_ID_OPUS;        apar->sample_rate = 48000;        return;    case MKBETAG('.', 'm', 'p', '3'):        apar->codec_id = AV_CODEC_ID_MP3;        return;    case MKBETAG('f', 'L', 'a', 'C'):        apar->codec_id = AV_CODEC_ID_FLAC;        return;    case MKBETAG('a', 'c', '-', '3'):        apar->codec_id = AV_CODEC_ID_AC3;        return;    case MKBETAG('e', 'c', '-', '3'):        apar->codec_id = AV_CODEC_ID_EAC3;        return;    default:        avpriv_request_sample(s, "Audio codec (%x)",               flv_codecid >> FLV_AUDIO_CODECID_OFFSET);        apar->codec_tag = flv_codecid >> FLV_AUDIO_CODECID_OFFSET;    }} static int flv_same_video_codec(AVCodecParameters *vpar, uint32_t flv_codecid){    if (!vpar->codec_id && !vpar->codec_tag)        return 1;     switch (flv_codecid) {    case FLV_CODECID_X_HEVC:    case MKBETAG('h', 'v', 'c', '1'):        return vpar->codec_id == AV_CODEC_ID_HEVC;    case MKBETAG('a', 'v', '0', '1'):        return vpar->codec_id == AV_CODEC_ID_AV1;    case MKBETAG('v', 'p', '0', '9'):        return vpar->codec_id == AV_CODEC_ID_VP9;    case FLV_CODECID_H263:        return vpar->codec_id == AV_CODEC_ID_FLV1;    case FLV_CODECID_SCREEN:        return vpar->codec_id == AV_CODEC_ID_FLASHSV;    case FLV_CODECID_SCREEN2:        return vpar->codec_id == AV_CODEC_ID_FLASHSV2;    case FLV_CODECID_VP6:        return vpar->codec_id == AV_CODEC_ID_VP6F;    case FLV_CODECID_VP6A:        return vpar->codec_id == AV_CODEC_ID_VP6A;    case FLV_CODECID_H264:    case MKBETAG('a', 'v', 'c', '1'):        return vpar->codec_id == AV_CODEC_ID_H264;    default:        return vpar->codec_tag == flv_codecid;    }} static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream,                               uint32_t flv_codecid, int read){    FFStream *const vstreami = ffstream(vstream);    int ret = 0;    AVCodecParameters *par = vstream->codecpar;    enum AVCodecID old_codec_id = vstream->codecpar->codec_id;     switch (flv_codecid) {    case FLV_CODECID_X_HEVC:    case MKBETAG('h', 'v', 'c', '1'):        par->codec_id = AV_CODEC_ID_HEVC;        vstreami->need_parsing = AVSTREAM_PARSE_HEADERS;        break;    case MKBETAG('a', 'v', '0', '1'):        par->codec_id = AV_CODEC_ID_AV1;        vstreami->need_parsing = AVSTREAM_PARSE_HEADERS;        break;    case MKBETAG('v', 'p', '0', '9'):        par->codec_id = AV_CODEC_ID_VP9;        vstreami->need_parsing = AVSTREAM_PARSE_HEADERS;        break;    case FLV_CODECID_H263:        par->codec_id = AV_CODEC_ID_FLV1;        break;    case FLV_CODECID_REALH263:        par->codec_id = AV_CODEC_ID_H263;        break; // Really mean it this time    case FLV_CODECID_SCREEN:        par->codec_id = AV_CODEC_ID_FLASHSV;        break;    case FLV_CODECID_SCREEN2:        par->codec_id = AV_CODEC_ID_FLASHSV2;        break;    case FLV_CODECID_VP6:        par->codec_id = AV_CODEC_ID_VP6F;    case FLV_CODECID_VP6A:        if (flv_codecid == FLV_CODECID_VP6A)            par->codec_id = AV_CODEC_ID_VP6A;        if (read) {            if (par->extradata_size != 1) {                ff_alloc_extradata(par, 1);            }            if (par->extradata)                par->extradata[0] = avio_r8(s->pb);            else                avio_skip(s->pb, 1);        }        ret = 1;     // 1 byte body size adjustment for flv_read_packet()        break;    case FLV_CODECID_H264:    case MKBETAG('a', 'v', 'c', '1'):        par->codec_id = AV_CODEC_ID_H264;        vstreami->need_parsing = AVSTREAM_PARSE_HEADERS;        break;    case FLV_CODECID_MPEG4:        par->codec_id = AV_CODEC_ID_MPEG4;        break;    default:        avpriv_request_sample(s, "Video codec (%x)", flv_codecid);        par->codec_tag = flv_codecid;    }     if (!vstreami->need_context_update && par->codec_id != old_codec_id) {        avpriv_request_sample(s, "Changing the codec id midstream");        return AVERROR_PATCHWELCOME;    }     return ret;} static int amf_get_string(AVIOContext *ioc, char *buffer, int buffsize){    int ret;    int length = avio_rb16(ioc);    if (length >= buffsize) {        avio_skip(ioc, length);        return -1;    }     ret = avio_read(ioc, buffer, length);    if (ret < 0)        return ret;    if (ret < length)        return AVERROR_INVALIDDATA;     buffer[length] = '\0';     return length;} static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, int64_t max_pos)

Lines 1–500 of 1958.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t