+
+ pkt->dts = dts;
+ pkt->pts = dts;
+ pkt->size = ret;
+
+ pkt->stream_index = st->index;
+ pkt->flags |= AV_PKT_FLAG_KEY;
+
+skip:
+ avio_seek(s->pb, next + 4, SEEK_SET);
+
+ return ret;
+}
+
+static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ FLVContext *flv = s->priv_data;
+ int ret, i, size, flags, is_audio;
+ enum FlvTagType type;
+ int64_t next, pos;
+ int64_t dts, pts = AV_NOPTS_VALUE;
+ int sample_rate = 0, channels = 0;
+ AVStream *st = NULL;
+
+ /* pkt size is repeated at end. skip it */
+ for (;; avio_skip(s->pb, 4)) {
+ pos = avio_tell(s->pb);
+ type = avio_r8(s->pb);
+ size = avio_rb24(s->pb);
+ dts = avio_rb24(s->pb);
+ dts |= avio_r8(s->pb) << 24;
+ av_log(s, AV_LOG_TRACE, "type:%d, size:%d, dts:%"PRId64"\n", type, size, dts);
+ if (s->pb->eof_reached)
+ return AVERROR_EOF;
+ avio_skip(s->pb, 3); /* stream id, always 0 */
+ flags = 0;
+
+ if (flv->validate_next < flv->validate_count) {
+ int64_t validate_pos = flv->validate_index[flv->validate_next].pos;
+ if (pos == validate_pos) {
+ if (FFABS(dts - flv->validate_index[flv->validate_next].dts) <=
+ VALIDATE_INDEX_TS_THRESH) {
+ flv->validate_next++;
+ } else {
+ clear_index_entries(s, validate_pos);
+ flv->validate_count = 0;
+ }
+ } else if (pos > validate_pos) {
+ clear_index_entries(s, validate_pos);
+ flv->validate_count = 0;
+ }
+ }
+
+ if (size == 0)
+ continue;
+
+ next = size + avio_tell(s->pb);
+
+ if (type == FLV_TAG_TYPE_AUDIO) {
+ is_audio = 1;
+ flags = avio_r8(s->pb);
+ size--;
+ } else if (type == FLV_TAG_TYPE_VIDEO) {
+ is_audio = 0;
+ flags = avio_r8(s->pb);
+ size--;
+ if ((flags & 0xf0) == 0x50) /* video info / command frame */
+ goto skip;
+ } else {
+ if (type == FLV_TAG_TYPE_META && size > 13 + 1 + 4)
+ if (flv_read_metabody(s, next) > 0) {
+ return flv_data_packet(s, pkt, dts, next);
+ } else /* skip packet */
+ av_log(s, AV_LOG_DEBUG,
+ "Skipping flv packet: type %d, size %d, flags %d.\n",
+ type, size, flags);
+
+skip:
+ avio_seek(s->pb, next, SEEK_SET);
+ continue;
+ }
+
+ /* skip empty data packets */
+ if (!size)
+ continue;
+
+ /* now find stream */
+ for (i = 0; i < s->nb_streams; i++) {
+ st = s->streams[i];
+ if (is_audio && st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+ if (flv_same_audio_codec(st->codec, flags))
+ break;
+ } else if (!is_audio &&
+ st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+ if (flv_same_video_codec(st->codec, flags))
+ break;
+ }
+ }
+ if (i == s->nb_streams) {
+ st = create_stream(s, is_audio ? AVMEDIA_TYPE_AUDIO
+ : AVMEDIA_TYPE_VIDEO);
+ if (!st)
+ return AVERROR(ENOMEM);
+ }
+ av_log(s, AV_LOG_TRACE, "%d %X %d \n", is_audio, flags, st->discard);
+
+ if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY ||
+ is_audio)
+ av_add_index_entry(st, pos, dts, size, 0, AVINDEX_KEYFRAME);
+
+ 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) {
+ avio_seek(s->pb, next, SEEK_SET);
+ continue;
+ }
+ break;