static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) { FLVContext *flv = s->priv_data; int ret, i, type, size, flags; int stream_type=-1; int64_t next, pos; int64_t dts, pts = AV_NOPTS_VALUE; int av_uninit(channels); int av_uninit(sample_rate); AVStream *st = NULL; for(;; avio_skip(s->pb, 4)) { /* pkt size is repeated at end. skip it */ 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_dlog(s, "type:%d, size:%d, dts:%"PRId64"\n", type, size, dts); if (url_feof(s->pb)) 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) { stream_type=FLV_STREAM_TYPE_AUDIO; flags = avio_r8(s->pb); size--; } else if (type == FLV_TAG_TYPE_VIDEO) { stream_type=FLV_STREAM_TYPE_VIDEO; flags = avio_r8(s->pb); size--; if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_VIDEO_INFO_CMD) goto skip; } else if (type == FLV_TAG_TYPE_META) { if (size > 13+1+4 && dts == 0) { // Header-type metadata stuff flv_read_metabody(s, next); goto skip; } else if (dts != 0) { // Script-data "special" metadata frames - don't skip stream_type=FLV_STREAM_TYPE_DATA; } else { goto skip; } } else { 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 (st->id == stream_type) break; } if(i == s->nb_streams) { av_log(s, AV_LOG_WARNING, "Stream discovered after head already parsed\n"); st = create_stream(s, stream_type, (int[]) { AVMEDIA_TYPE_VIDEO, AVMEDIA_TYPE_AUDIO, AVMEDIA_TYPE_DATA }[stream_type]); } av_dlog(s, "%d %X %d \n", stream_type, flags, st->discard); if( (st->discard >= AVDISCARD_NONKEY && !((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY || (stream_type == FLV_STREAM_TYPE_AUDIO))) ||(st->discard >= AVDISCARD_BIDIR && ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_DISP_INTER && (stream_type == FLV_STREAM_TYPE_VIDEO))) || st->discard >= AVDISCARD_ALL ) { avio_seek(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; }
static int ReadPacket(flv* p, format_reader* Reader, format_packet* Packet) { format_stream* s; int i, type, size, TimeStamp, flags, is_audio; int64_t next; bool_t isNewStream = 0; filepos_t startfilepos; startfilepos = Reader->FilePos; for (;;) { Reader->Skip(Reader, 4);//prvious type size type = Reader->Read8(Reader); size = ReadBE24(Reader); TimeStamp = ReadBE24(Reader); if (Reader->Eof(Reader)) { return ERR_END_OF_FILE; } // Reserved Reader->Skip(Reader, 4); flags = 0; if (size == 0) continue; next = size + Reader->FilePos; if (type == FLV_TAG_TYPE_AUDIO) { is_audio = 1; flags = Reader->Read8(Reader); size--; p->bHasA = 1; } else if (type == FLV_TAG_TYPE_VIDEO) { is_audio = 0; flags = Reader->Read8(Reader); size--; p->bHasV = 1; } else if (type == FLV_TAG_TYPE_META && size > 13+1+4) { if(flv_read_metabody(p,Reader, next)<0) { Reader->Seek(Reader,(filepos_t)next,SEEK_SET); } continue; } else { // Skip the packet Reader->Skip(Reader, size); continue; } // Now find stream s = NULL; for (i=0;i<p->Format.StreamCount;++i) { if (p->Format.Streams[i]->Id == is_audio) { s = p->Format.Streams[i]; break; } } if (!s) { s = Format_AddStream(&p->Format,sizeof(format_stream)); if (!s) return ERR_OUT_OF_MEMORY; s->Id = is_audio; isNewStream = 1; s->Format.PacketRate.Den = 24; s->Format.PacketRate.Num = 1000; } break; } if(is_audio) { if (isNewStream) { int bInited = 0; PacketFormatClear(&s->Format); s->Format.Type = PACKET_AUDIO; s->Format.Format.Audio.Channels = (flags&1)+1; if((flags >> 4) == 5) s->Format.Format.Audio.SampleRate = 8000; else s->Format.Format.Audio.SampleRate = (44100<<((flags>>2)&3))>>3; switch(flags >> 4) {/* 0: uncompressed 1: ADPCM 2: mp3 5: Nellymoser 8kHz mono 6: Nellymoser */ case FLV_CODECID_PCM: s->Format.Format.Audio.Format = AUDIOFMT_PCM; if (!(flags&2)) { s->Format.Format.Audio.Bits = 8; s->Format.Format.Audio.FracBits = 7; bInited = 1; } break; case FLV_CODECID_ADPCM: s->Format.Format.Audio.Format = AUDIOFMT_ADPCM_SWF; break; case FLV_CODECID_MP3: s->Format.Format.Audio.Format = AUDIOFMT_MP3; break; case FLV_CODECID_PCM_LE: s->Format.Format.Audio.Format = AUDIOFMT_PCM; if (!(flags&2)) { s->Format.Format.Audio.Bits = 8; s->Format.Format.Audio.FracBits = 7; bInited = 1; } break; case FLV_CODECID_NELLYMOSER_8KHZ_MONO: s->Format.Format.Audio.SampleRate = 8000; case FLV_CODECID_NELLYMOSER: s->Format.Format.Audio.Format = AUDIOFMT_NELLYMOSER; break; case FLV_CODECID_AAC: { format_stream* s; int type = Reader->Read8(Reader); size--; if(type == 0) { s = p->Format.Streams[p->Format.StreamCount-1]; if (PacketFormatExtra(&s->Format,size)) Reader->Read(Reader,s->Format.Extra,size); } s->Format.Format.Audio.Format = AUDIOFMT_AAC; Format_PrepairStream(&p->Format, s); } return ERR_NONE; case FLV_CODECID_SPEEX: s->Format.Format.Audio.Format = AUDIOFMT_SPEEX; s->Format.Format.Audio.SampleRate = 16000; break; default: return ERR_NOT_SUPPORTED; } if(!bInited) { s->Format.Format.Audio.Bits = 16; s->Format.Format.Audio.FracBits = 15; } s->Format.ByteRate = s->Format.Format.Audio.SampleRate * s->Format.Format.Audio.Channels * 2; Format_PrepairStream(&p->Format,s); } }