[FFmpeg-devel] [PATCH 12/12] asfdec: read the index while reading the header, not on first seek
Anton Khirnov
anton
Wed Feb 9 21:56:02 CET 2011
it makes more sense and gets rid of a variable from ASFContext.
asf_build_simple_index() is changed to use ASFContext.data_ofsset
instead of AVFormatContext.data_offset, since the latter isn't set yet.
---
libavformat/asfdec.c | 136 ++++++++++++++++++++++++--------------------------
1 files changed, 66 insertions(+), 70 deletions(-)
diff --git a/libavformat/asfdec.c b/libavformat/asfdec.c
index 648dbd5..677d35a 100644
--- a/libavformat/asfdec.c
+++ b/libavformat/asfdec.c
@@ -44,7 +44,6 @@ typedef struct {
uint64_t data_offset; ///< beginning of the first data packet
uint64_t data_object_offset; ///< data object offset (excl. GUID & size)
uint64_t data_object_size; ///< size of the data object
- int index_read;
ASFMainHeader hdr;
@@ -563,6 +562,69 @@ static int asf_read_marker(AVFormatContext *s, int64_t size)
return 0;
}
+static void asf_build_simple_index(AVFormatContext *s)
+{
+ ff_asf_guid g;
+ ASFContext *asf = s->priv_data;
+ int64_t current_pos= url_ftell(s->pb);
+ int i, stream_index = 0;
+ AVStream *st;
+
+ url_fseek(s->pb, asf->data_object_offset + asf->data_object_size, SEEK_SET);
+ ff_get_guid(s->pb, &g);
+
+ /* the data object can be followed by other top-level objects,
+ skip them until the simple index object is reached */
+ while (ff_guidcmp(&g, &ff_asf_guid_simple_index)) {
+ int64_t gsize= get_le64(s->pb);
+ if (gsize < 24 || url_feof(s->pb)) {
+ url_fseek(s->pb, current_pos, SEEK_SET);
+ return;
+ }
+ url_fseek(s->pb, gsize-24, SEEK_CUR);
+ ff_get_guid(s->pb, &g);
+ }
+
+ while (!ff_guidcmp(&g, &ff_asf_guid_simple_index)) {
+ int64_t itime, last_pos=-1;
+ int pct, ict;
+ int64_t av_unused gsize= get_le64(s->pb);
+ ff_get_guid(s->pb, &g);
+ itime=get_le64(s->pb);
+ pct=get_le32(s->pb);
+ ict=get_le32(s->pb);
+ av_log(s, AV_LOG_DEBUG, "itime:0x%"PRIx64", pct:%d, ict:%d\n",itime,pct,ict);
+
+ /* find next video stream */
+ for (i = stream_index; i < s->nb_streams; i++) {
+ st = s->streams[i];
+ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+ stream_index = i;
+ break;
+ }
+ }
+ if (i == s->nb_streams) {
+ av_log(s, AV_LOG_ERROR, "Found an index not corresponding to any stream.\n");
+ return;
+ }
+
+ for (i=0;i<ict;i++){
+ int pktnum=get_le32(s->pb);
+ int pktct =get_le16(s->pb);
+ int64_t pos = asf->data_offset + s->packet_size*(int64_t)pktnum;
+ int64_t index_pts= av_rescale(itime, i, 10000);
+
+ if(pos != last_pos){
+ av_log(s, AV_LOG_DEBUG, "pktnum:%d, pktct:%d\n", pktnum, pktct);
+ av_add_index_entry(st, pos, index_pts, s->packet_size, 0, AVINDEX_KEYFRAME);
+ last_pos=pos;
+ }
+ }
+ ff_get_guid(s->pb, &g);
+ }
+ url_fseek(s->pb, current_pos, SEEK_SET);
+}
+
static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
{
ASFContext *asf = s->priv_data;
@@ -650,6 +712,8 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
asf->data_offset = url_ftell(pb);
asf->packet_size_left = 0;
+ if (!(url_is_streamed(s->pb) || s->flags & AVFMT_FLAG_IGNIDX))
+ asf_build_simple_index(s);
for(i=0; i<128; i++){
int stream_num= asf->asfid2avid[i];
@@ -1145,73 +1209,8 @@ static int64_t asf_read_pts(AVFormatContext *s, int stream_index, int64_t *ppos,
return pts;
}
-static void asf_build_simple_index(AVFormatContext *s)
-{
- ff_asf_guid g;
- ASFContext *asf = s->priv_data;
- int64_t current_pos= url_ftell(s->pb);
- int i, stream_index = 0;
- AVStream *st;
-
- url_fseek(s->pb, asf->data_object_offset + asf->data_object_size, SEEK_SET);
- ff_get_guid(s->pb, &g);
-
- /* the data object can be followed by other top-level objects,
- skip them until the simple index object is reached */
- while (ff_guidcmp(&g, &ff_asf_guid_simple_index)) {
- int64_t gsize= get_le64(s->pb);
- if (gsize < 24 || url_feof(s->pb)) {
- url_fseek(s->pb, current_pos, SEEK_SET);
- return;
- }
- url_fseek(s->pb, gsize-24, SEEK_CUR);
- ff_get_guid(s->pb, &g);
- }
-
- while (!ff_guidcmp(&g, &ff_asf_guid_simple_index)) {
- int64_t itime, last_pos=-1;
- int pct, ict;
- int64_t av_unused gsize= get_le64(s->pb);
- ff_get_guid(s->pb, &g);
- itime=get_le64(s->pb);
- pct=get_le32(s->pb);
- ict=get_le32(s->pb);
- av_log(s, AV_LOG_DEBUG, "itime:0x%"PRIx64", pct:%d, ict:%d\n",itime,pct,ict);
-
- /* find next video stream */
- for (i = stream_index; i < s->nb_streams; i++) {
- st = s->streams[i];
- if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
- stream_index = i;
- break;
- }
- }
- if (i == s->nb_streams) {
- av_log(s, AV_LOG_ERROR, "Found an index not corresponding to any stream.\n");
- return;
- }
-
- for (i=0;i<ict;i++){
- int pktnum=get_le32(s->pb);
- int pktct =get_le16(s->pb);
- int64_t pos = s->data_offset + s->packet_size*(int64_t)pktnum;
- int64_t index_pts= av_rescale(itime, i, 10000);
-
- if(pos != last_pos){
- av_log(s, AV_LOG_DEBUG, "pktnum:%d, pktct:%d\n", pktnum, pktct);
- av_add_index_entry(st, pos, index_pts, s->packet_size, 0, AVINDEX_KEYFRAME);
- last_pos=pos;
- }
- }
- asf->index_read= 1;
- ff_get_guid(s->pb, &g);
- }
- url_fseek(s->pb, current_pos, SEEK_SET);
-}
-
static int asf_read_seek(AVFormatContext *s, int stream_index, int64_t pts, int flags)
{
- ASFContext *asf = s->priv_data;
AVStream *st = s->streams[stream_index];
int64_t pos;
int index;
@@ -1228,10 +1227,7 @@ static int asf_read_seek(AVFormatContext *s, int stream_index, int64_t pts, int
return ret;
}
- if (!asf->index_read)
- asf_build_simple_index(s);
-
- if(!(asf->index_read && st->index_entries)){
+ if(!st->index_entries){
if(av_seek_frame_binary(s, stream_index, pts, flags)<0)
return -1;
}else{
--
1.7.2.3
More information about the ffmpeg-devel
mailing list