📄 flvdec.c
字号:
keylen = 0; ioc = s->pb; //first object needs to be "onMetaData" string type = get_byte(ioc); if(type != AMF_DATA_TYPE_STRING || amf_get_string(ioc, buffer, sizeof(buffer)) < 0 || strcmp(buffer, "onMetaData")) return -1; //find the streams now so that amf_parse_object doesn't need to do the lookup every time it is called. for(i = 0; i < s->nb_streams; i++) { stream = s->streams[i]; if (stream->codec->codec_type == CODEC_TYPE_AUDIO) astream = stream; else if(stream->codec->codec_type == CODEC_TYPE_VIDEO) vstream = stream; } //parse the second object (we want a mixed array) if(amf_parse_object(s, astream, vstream, buffer, next_pos, 0) < 0) return -1; return 0;}static AVStream *create_stream(AVFormatContext *s, int is_audio){ AVStream *st = av_new_stream(s, is_audio); if (!st) return NULL; st->codec->codec_type = is_audio ? CODEC_TYPE_AUDIO : CODEC_TYPE_VIDEO; av_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */ return st;}static int flv_read_header(AVFormatContext *s, AVFormatParameters *ap){ int offset, flags; url_fskip(s->pb, 4); flags = get_byte(s->pb); /* old flvtool cleared this field */ /* FIXME: better fix needed */ if (!flags) { flags = FLV_HEADER_FLAG_HASVIDEO | FLV_HEADER_FLAG_HASAUDIO; av_log(s, AV_LOG_WARNING, "Broken FLV file, which says no streams present, this might fail\n"); } if((flags & (FLV_HEADER_FLAG_HASVIDEO|FLV_HEADER_FLAG_HASAUDIO)) != (FLV_HEADER_FLAG_HASVIDEO|FLV_HEADER_FLAG_HASAUDIO)) s->ctx_flags |= AVFMTCTX_NOHEADER; if(flags & FLV_HEADER_FLAG_HASVIDEO){ if(!create_stream(s, 0)) return AVERROR(ENOMEM); } if(flags & FLV_HEADER_FLAG_HASAUDIO){ if(!create_stream(s, 1)) return AVERROR(ENOMEM); } offset = get_be32(s->pb); url_fseek(s->pb, offset, SEEK_SET); s->start_time = 0; return 0;}static int flv_get_extradata(AVFormatContext *s, AVStream *st, int size){ av_free(st->codec->extradata); st->codec->extradata = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE); if (!st->codec->extradata) return AVERROR(ENOMEM); st->codec->extradata_size = size; get_buffer(s->pb, st->codec->extradata, st->codec->extradata_size); return 0;}static int flv_read_packet(AVFormatContext *s, AVPacket *pkt){ int ret, i, type, size, flags, is_audio, next, pos; unsigned dts; AVStream *st = NULL; retry: for(;;){ pos = url_ftell(s->pb); url_fskip(s->pb, 4); /* size of previous packet */ type = get_byte(s->pb); size = get_be24(s->pb); dts = get_be24(s->pb); dts |= get_byte(s->pb) << 24;// av_log(s, AV_LOG_DEBUG, "type:%d, size:%d, dts:%d\n", type, size, dts); if (url_feof(s->pb)) return AVERROR(EIO); url_fskip(s->pb, 3); /* stream id, always 0 */ flags = 0; if(size == 0) continue; next= size + url_ftell(s->pb); if (type == FLV_TAG_TYPE_AUDIO) { is_audio=1; flags = get_byte(s->pb); } else if (type == FLV_TAG_TYPE_VIDEO) { is_audio=0; flags = get_byte(s->pb); } else { if (type == FLV_TAG_TYPE_META && size > 13+1+4) flv_read_metabody(s, next); else /* skip packet */ av_log(s, AV_LOG_ERROR, "skipping flv packet: type %d, size %d, flags %d\n", type, size, flags); url_fseek(s->pb, next, SEEK_SET); continue; } /* now find stream */ for(i=0;i<s->nb_streams;i++) { st = s->streams[i]; if (st->id == is_audio) break; } if(i == s->nb_streams){ av_log(NULL, AV_LOG_ERROR, "invalid stream\n"); st= create_stream(s, is_audio); s->ctx_flags &= ~AVFMTCTX_NOHEADER; }// av_log(NULL, AV_LOG_DEBUG, "%d %X %d \n", is_audio, flags, st->discard); if( (st->discard >= AVDISCARD_NONKEY && !((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY || is_audio)) ||(st->discard >= AVDISCARD_BIDIR && ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_DISP_INTER && !is_audio)) || st->discard >= AVDISCARD_ALL ){ url_fseek(s->pb, next, SEEK_SET); continue; } if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY) av_add_index_entry(st, pos, dts, size, 0, AVINDEX_KEYFRAME); break; } // if not streamed and no duration from metadata then seek to end to find the duration from the timestamps if(!url_is_streamed(s->pb) && s->duration==AV_NOPTS_VALUE){ int size; const int pos= url_ftell(s->pb); const int fsize= url_fsize(s->pb); url_fseek(s->pb, fsize-4, SEEK_SET); size= get_be32(s->pb); url_fseek(s->pb, fsize-3-size, SEEK_SET); if(size == get_be24(s->pb) + 11){ s->duration= get_be24(s->pb) * (int64_t)AV_TIME_BASE / 1000; } url_fseek(s->pb, pos, SEEK_SET); } if(is_audio){ if(!st->codec->sample_rate || !st->codec->bits_per_sample || (!st->codec->codec_id && !st->codec->codec_tag)) { st->codec->channels = (flags & FLV_AUDIO_CHANNEL_MASK) == FLV_STEREO ? 2 : 1; if((flags & FLV_AUDIO_CODECID_MASK) == FLV_CODECID_NELLYMOSER_8HZ_MONO) st->codec->sample_rate= 8000; else st->codec->sample_rate = (44100 << ((flags & FLV_AUDIO_SAMPLERATE_MASK) >> FLV_AUDIO_SAMPLERATE_OFFSET) >> 3); st->codec->bits_per_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8; flv_set_audio_codec(s, st, flags & FLV_AUDIO_CODECID_MASK); } }else{ size -= flv_set_video_codec(s, st, flags & FLV_VIDEO_CODECID_MASK); } if (st->codec->codec_id == CODEC_ID_AAC || st->codec->codec_id == CODEC_ID_H264) { int type = get_byte(s->pb); size--; if (st->codec->codec_id == CODEC_ID_H264) { // cts offset ignored because it might to be signed // and would cause pts < dts get_be24(s->pb); } if (type == 0) { if ((ret = flv_get_extradata(s, st, size - 1)) < 0) return ret; goto retry; } } ret= av_get_packet(s->pb, pkt, size - 1); if (ret <= 0) { return AVERROR(EIO); } /* note: we need to modify the packet size here to handle the last packet */ pkt->size = ret; pkt->dts = dts; pkt->stream_index = st->index; if (is_audio || ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY)) pkt->flags |= PKT_FLAG_KEY; return ret;}AVInputFormat flv_demuxer = { "flv", NULL_IF_CONFIG_SMALL("FLV format"), 0, flv_probe, flv_read_header, flv_read_packet,#ifdef __CW32__ 0, 0, 0, 0, "flv", CODEC_ID_FLV1,#else .extensions = "flv", .value = CODEC_ID_FLV1,#endif};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -