Hi again,
I needed to recover exact packets, so on the first read I save all
packets with available timestamp value, then when I need I make an
av_seek_frame to these values in order to recover the corresponding
packet, but sometimes it worked and sometimes it sent me an other packet
(which is the next packet in fact).
and worst, sometimes it was simply impossible to seek to this same
timestamp, it returned the packet of the next timestamp :s
So I digg in... and I made a modification so when we make a seek to a
saved timestamp we always recover the same packet as the one which
generated this timestamp!
I join a patch if it can help!
NB : like for my previous mail, I think it should be better in
ffmpeg-devel mailing list, but I don't have acces to it...
diff -cr ffmpeg-export-2008-10-10/libavformat/oggdec.c ffmpeg-export-2008-10-10_modif/libavformat/oggdec.c
*** ffmpeg-export-2008-10-10/libavformat/oggdec.c 2008-10-03 12:16:29.000000000 +0200
--- ffmpeg-export-2008-10-10_modif/libavformat/oggdec.c 2008-11-18 17:36:37.000000000 +0100
***************
*** 119,124 ****
--- 119,125 ----
os->lastgp = -1;
os->nsegs = 0;
os->segp = 0;
+ os->timeStamped = 0;
}
ogg->curidx = -1;
***************
*** 291,297 ****
os->lastgp = os->granule;
os->bufpos += size;
os->granule = gp;
! os->flags = flags;
if (str)
*str = idx;
--- 292,299 ----
os->lastgp = os->granule;
os->bufpos += size;
os->granule = gp;
! os->flags = flags;;
! os->timeStamped=-1; //not yet timestamped, waiting for first full packet
if (str)
*str = idx;
***************
*** 320,326 ****
return -1;
}
! os = ogg->streams + idx;
#if 0
av_log (s, AV_LOG_DEBUG,
--- 322,331 ----
return -1;
}
! os = ogg->streams + idx;;
! if ((os->timeStamped==-1) && (!(os->flags&0x01) || (os->flags&0x01 && os->segp > 0) ) ){
! os->timeStamped=0; //this is the packet wich need to be timestamped!
! }
#if 0
av_log (s, AV_LOG_DEBUG,
***************
*** 513,521 ****
return AVERROR(EIO);
pkt->stream_index = idx;
memcpy (pkt->data, os->buf + pstart, psize);
! if (os->lastgp != -1LL){
pkt->pts = ogg_gptopts (s, idx, os->lastgp);
! os->lastgp = -1;
}
pkt->flags = os->pflags;
--- 518,526 ----
return AVERROR(EIO);
pkt->stream_index = idx;
memcpy (pkt->data, os->buf + pstart, psize);
! if (os->timeStamped == 0){
pkt->pts = ogg_gptopts (s, idx, os->lastgp);
! os->timeStamped = 1; //page timestamped
}
pkt->flags = os->pflags;
***************
*** 552,559 ****
if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
ogg->streams[i].codec && i == stream_index) {
pts = ogg_gptopts(s, i, ogg->streams[i].granule);
! // FIXME: this is the position of the packet after the one with above
! // pts.
*pos_arg = url_ftell(bc);
break;
}
--- 557,584 ----
if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
ogg->streams[i].codec && i == stream_index) {
pts = ogg_gptopts(s, i, ogg->streams[i].granule);
! // FIXME: this is the position of the packet after the one with above pts.
! // ==> if we got a page type "fresh packet" so the firts packet is full (I mean present from its begining) then we will have the real first packet of this page sequence
! // ==> but if we have a page type "continued packet" then we will have the second packet (because it's too complicated to go recover the begining of the first packet in the previous page)
! //
! // Problem is:
! // we read a packet with a timestamp, we save this timestamp for future seek
! // we want to recover the packet, so we make a seek->timestamp
! // first case:
! // it was a packet with the begining on this frame ("fresh packet")
! // then it will return the first FULL packet which is the real first packet of the frame
! // second case:
! // it was a packet with the begining on the previous frame ("continued packet")
! // then we cannot recover the begining in the previous frame
! // so it will return the first FULL packet in that frame which is the second packet of the frame!
! // And so we will not recover the same packet than the one which gave us the timestamp!
! //
! // To manage this problem, we always apply a timestamp to the second packet
! // and av_seek_frame->timestamp always put the pointer on the second packet
! // so we have a predictible behaviour
! // => when av_read_frame return a timestamp it is the second packet for sure
! // and av_seek_frame will always return the same packet as the one which gave us the timestamp!
!
*pos_arg = url_ftell(bc);
break;
}
diff -cr ffmpeg-export-2008-10-10/libavformat/oggdec.h ffmpeg-export-2008-10-10_modif/libavformat/oggdec.h
*** ffmpeg-export-2008-10-10/libavformat/oggdec.h 2008-08-31 09:39:47.000000000 +0200
--- ffmpeg-export-2008-10-10_modif/libavformat/oggdec.h 2008-11-18 17:38:21.000000000 +0100
***************
*** 51,56 ****
--- 51,57 ----
int header;
int nsegs, segp;
uint8_t segments[255];
+ int8_t timeStamped; //flag to indicate when to timestamp a packet
void *private;
} ogg_stream_t;
diff -cr ffmpeg-export-2008-10-10/libavformat/utils.c ffmpeg-export-2008-10-10_modif/libavformat/utils.c
*** ffmpeg-export-2008-10-10/libavformat/utils.c 2008-10-03 12:16:29.000000000 +0200
--- ffmpeg-export-2008-10-10_modif/libavformat/utils.c 2008-11-18 17:07:33.000000000 +0100
***************
*** 1421,1430 ****
are very few or no keyframes between min/max */
pos=pos_min;
}
! if(pos <= pos_min)
! pos= pos_min + 1;
! else if(pos > pos_limit)
pos= pos_limit;
start_pos= pos;
ts = read_timestamp(s, stream_index, &pos, INT64_MAX); //may pass pos_limit instead of -1
--- 1421,1431 ----
are very few or no keyframes between min/max */
pos=pos_min;
}
! if(pos < pos_min) // <yvan:> changed '<=' to '<'
! pos= pos_min; // and removed +1 here because otherwise some frame are dropped (at least with ogg)
! else if(pos > pos_limit)
pos= pos_limit;
+
start_pos= pos;
ts = read_timestamp(s, stream_index, &pos, INT64_MAX); //may pass pos_limit instead of -1
_______________________________________________
libav-user mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/libav-user