[FFmpeg-devel] [PATCH] First shot at AVCHD seeking via new seeking API
Ivan Schreter
schreter
Sun Aug 30 10:11:21 CEST 2009
Hi Baptiste,
sorry for getting back to you so late, but unfortunately, I don't have
much time to work on FFmpeg :-(
Baptiste Coudurier wrote:
> [...]
>> + int64_t term_ts; ///< Termination timestamp (which TS we
>> already read).
>> + int64_t first_ts; ///< First packet timestamp in this
>> iteration (to fill term_ts later).
>> + int terminated; ///< Termination flag for current iteration.
>
> I still don't like these fields, especially terminated.
I know you don't like them, but IMHO that's the only way to handle
interleaved streams like MPEG-TS properly.
An alternative would be keeping one position or timestamp which contains
local maximum of position or timestamp of first packets from all streams
from previous iteration (oh, complicated to understand :-) and in
current iteration reading until all streams return a packet with a
position past this position or timestamp.
The disadvantage with a single position/timestamp is, you have to
evaluate packets of one stream several times then. It is no harm, but
with current code, I feel it's cleaner.
Simply reading until fpos is >= previous start fpos is not enough, since
there are interleaved packets, which actually cross the position, as I
already pointed out twice.
>
> > [...]
> >
>> + if (sp->pos_hi == INT64_MAX) {
>> + // No high frame exists for this stream
>> + (*found_hi)++;
>> + sp->pts_hi = INT64_MAX;
>> + sp->pos_hi = INT64_MAX - 1;
>
> Why are you setting these fields to these values ?
>
As the comment says, we didn't find a high frame for the stream. PTS is
thus set to invalid. Position must be set to something else, otherwise
it could run into this or another if block comparing undefined pos_hi
(effectively, meaning high frame not yet found) and then increment
number of found high frames again. But number of found high frames must
be incremented exactly once per stream.
Alternative would be to introduce new fields found_hi and found_lo in
syncpoint structure per stream and instead of testing pos_hi/pos_lo for
INT64_MAX, check those flags. Shall I rework it that way?
>> [...]
>>
>> +
>> + if (ts<= timestamp) {
>> + // Keyframe found before target timestamp.
>> + if (sp->pos_lo == INT64_MAX) {
>> + // Found first keyframe lower than target
>> timestamp.
>> + (*found_lo)++;
>> + sp->pts_lo = ts;
>> + sp->pos_lo = pos;
>> + } else if (sp->pts_lo< ts) {
>> + // Found a better match (closer to target
>> timestamp).
>> + sp->pts_lo = ts;
>> + sp->pos_lo = pos;
>> + }
>
> Hummm, it's the same code, if (sp->pos_lo == INT64_MAX || sp->pts_lo <
> ts) ?
>
> It will simplify the code.
>
It's not the same code. In first branch, number of already-found low
frames is increased, in other one not. Thus, if I'd do it in one block,
I'd have to add another if condition inside the block checking pos_lo
for INT64_MAX and only then incrementing number of found lo frames.
But if you wish, I can rewrite it that way. Shall I do it?
> Btw why don't you set pos_lo to INT64_MIN ? It would make more sense.
>
Both would do. It's basically a flag value. Would you set pos_lo to
INT64_MIN? What then with pos_hi? Maybe AV_NOPTS_VALUE would be more proper?
What do you think?
>> + }
>> + if (ts>= timestamp) {
>> + // Keyframe found after target timestamp.
>> + if (sp->pos_hi == INT64_MAX) {
>> + // Found first keyframe higher than target
>> timestamp.
>> + (*found_hi)++;
>> + sp->pts_hi = ts;
>> + sp->pos_hi = pos;
>> + if (*found_hi>= keyframes_to_find&& first_iter) {
>> + // We found high frame for all. They may get
>> updated
>> + // to TS closer to target TS in later
>> iterations (which
>> + // will stop at start position of previous
>> iteration).
>> + break;
>> + }
>> + } else if (sp->pts_hi> ts) {
>> + // Found a better match (actually, shouldn't
>> happen).
>> + sp->pts_hi = ts;
>> + sp->pos_hi = pos;
>> + }
>
> Same comment.
Again, same as above. In the if() condition, another nested if() would
be needed.
>
> > [...]
>>
>> +}
>> +
>> +static void free_packet_list(AVPacketList *pktl)
>> +{
>> + AVPacketList *cur;
>> + while (pktl) {
>> + cur = pktl;
>> + pktl = cur->next;
>> + av_free_packet(&cur->pkt);
>> + av_free(cur);
>> + }
>
> I think this function would be useful in utils.c and
> flush_packet_queue could use it.
>
Surely. Let's keep this on a TODO list. Is there somewhere a common one?
I think it generally makes sense to reorganize the code a bit
(especially seeking-related functions) and put some functions elsewhere.
BTW, I found out that pure seeking routine time can be reduced about
factor 3 for full-HD AVCHD files, when using higher initial step size
(32KB) for back-off. I will investigate how this step size could be
automagically determined optimally.
Regards,
Ivan
More information about the ffmpeg-devel
mailing list