赞
踩
cur_seq_no
和seek_timestamp
cur_seq_no
上的流,一直读到符合当前seek_timestamp
和seek_flags
的流才返回,所以seek之后第一次读数据会比较慢static int hls_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { HLSContext *c = s->priv_data; struct playlist *seek_pls = NULL; int i, seq_no; int j; int stream_subdemuxer_index; int64_t first_timestamp, seek_timestamp, duration; // hls不支持byte方式的seek,并判断是否支持seek,hls的seek状态会动态改变的 if ((flags & AVSEEK_FLAG_BYTE) || (c->ctx->ctx_flags & AVFMTCTX_UNSEEKABLE)) return AVERROR(ENOSYS); first_timestamp = c->first_timestamp == AV_NOPTS_VALUE ? 0 : c->first_timestamp; // 计算以time_base为倍数的时间戳 seek_timestamp = av_rescale_rnd(timestamp, AV_TIME_BASE, s->streams[stream_index]->time_base.den, flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP); duration = s->duration == AV_NOPTS_VALUE ? 0 : s->duration; if (0 < duration && duration < seek_timestamp - first_timestamp) return AVERROR(EIO); /* find the playlist with the specified stream */ for (i = 0; i < c->n_playlists; i++) { struct playlist *pls = c->playlists[i]; for (j = 0; j < pls->n_main_streams; j++) { if (pls->main_streams[j] == s->streams[stream_index]) { seek_pls = pls; stream_subdemuxer_index = j; break; } } } /* check if the timestamp is valid for the playlist with the specified stream index */ if (!seek_pls || !find_timestamp_in_playlist(c, seek_pls, seek_timestamp, &seq_no)) return AVERROR(EIO); /* set segment now so we do not need to search again below */ seek_pls->cur_seq_no = seq_no; seek_pls->seek_stream_index = stream_subdemuxer_index; for (i = 0; i < c->n_playlists; i++) { /* Reset reading */ struct playlist *pls = c->playlists[i]; if (pls->input) ff_format_io_close(pls->parent, &pls->input); pls->input_read_done = 0; if (pls->input_next) ff_format_io_close(pls->parent, &pls->input_next); pls->input_next_requested = 0; av_packet_unref(&pls->pkt); reset_packet(&pls->pkt); pls->pb.eof_reached = 0; /* Clear any buffered data */ pls->pb.buf_end = pls->pb.buf_ptr = pls->pb.buffer; /* Reset the pos, to let the mpegts demuxer know we've seeked. */ pls->pb.pos = 0; /* Flush the packet queue of the subdemuxer. */ ff_read_frame_flush(pls->ctx); pls->seek_timestamp = seek_timestamp; pls->seek_flags = flags; if (pls != seek_pls) { /* set closest segment seq_no for playlists not handled above */ find_timestamp_in_playlist(c, pls, seek_timestamp, &pls->cur_seq_no); /* seek the playlist to the given position without taking * keyframes into account since this playlist does not have the * specified stream where we should look for the keyframes */ pls->seek_stream_index = -1; pls->seek_flags |= AVSEEK_FLAG_ANY; } } c->cur_timestamp = seek_timestamp; return 0; }
static int hls_read_packet(AVFormatContext *s, AVPacket *pkt) { HLSContext *c = s->priv_data; int ret, i, minplaylist = -1; recheck_discard_flags(s, c->first_packet); c->first_packet = 0; for (i = 0; i < c->n_playlists; i++) { struct playlist *pls = c->playlists[i]; /* Make sure we've got one buffered packet from each open playlist * stream */ if (pls->needed && !pls->pkt.data) { while (1) { int64_t ts_diff; AVRational tb; ret = av_read_frame(pls->ctx, &pls->pkt); if (ret < 0) { if (!avio_feof(&pls->pb) && ret != AVERROR_EOF) return ret; reset_packet(&pls->pkt); break; } else { /* stream_index check prevents matching picture attachments etc. */ if (pls->is_id3_timestamped && pls->pkt.stream_index == 0) { /* audio elementary streams are id3 timestamped */ fill_timing_for_id3_timestamped_stream(pls); } if (c->first_timestamp == AV_NOPTS_VALUE && pls->pkt.dts != AV_NOPTS_VALUE) c->first_timestamp = av_rescale_q(pls->pkt.dts, get_timebase(pls), AV_TIME_BASE_Q); } if (pls->seek_timestamp == AV_NOPTS_VALUE) break; if (pls->seek_stream_index < 0 || pls->seek_stream_index == pls->pkt.stream_index) { if (pls->pkt.dts == AV_NOPTS_VALUE) { pls->seek_timestamp = AV_NOPTS_VALUE; break; } tb = get_timebase(pls); // 得到当前帧的时间戳和要seek的时间戳的差值 ts_diff = av_rescale_rnd(pls->pkt.dts, AV_TIME_BASE, tb.den, AV_ROUND_DOWN) - pls->seek_timestamp; // seek_flags就支持AVSEEK_FLAG_ANY和AV_PKT_FLAG_KEY,返回的帧一定是要晚于seek时间戳的 if (ts_diff >= 0 && (pls->seek_flags & AVSEEK_FLAG_ANY || pls->pkt.flags & AV_PKT_FLAG_KEY)) { pls->seek_timestamp = AV_NOPTS_VALUE; break; } } av_packet_unref(&pls->pkt); reset_packet(&pls->pkt); } } /* Check if this stream has the packet with the lowest dts */ if (pls->pkt.data) { struct playlist *minpls = minplaylist < 0 ? NULL : c->playlists[minplaylist]; if (minplaylist < 0) { minplaylist = i; } else { int64_t dts = pls->pkt.dts; int64_t mindts = minpls->pkt.dts; if (dts == AV_NOPTS_VALUE || (mindts != AV_NOPTS_VALUE && compare_ts_with_wrapdetect(dts, pls, mindts, minpls) < 0)) minplaylist = i; } } } ... /* If we got a packet, return it */ if (minplaylist >= 0) { ... return 0; } return AVERROR_EOF; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。