AVPacket on MPEG-2 PS has dts!=AV_NOPTS_VALUE and pts=AV_NOPTS_VALUE.
Can not be added in the case of pts=AV_NOPTS_VALUE because pts is key in
put_dts()/get_dts().
It is difficult to guess pts from AVPacket.
So, use sequential number as key.
If input the bitstream with the TimeStamp of the sequential number to QSV
decoder,
it output the strange TimeStamp value of last frame.
So, convert to timestamp format the sequential number.
---
libavcodec/qsv.c | 57 +++++++++++++++++++++++++++-----------------------------
libavcodec/qsv.h | 4 +++-
2 files changed, 30 insertions(+), 31 deletions(-)
diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
index c539536..6e69e52 100644
--- a/libavcodec/qsv.c
+++ b/libavcodec/qsv.c
@@ -87,7 +87,7 @@ static int codec_id_to_mfx(enum AVCodecID codec_id)
static void reset_timestamps(QSVContext *q)
{
for (int i = 0; i < q->nb_timestamps; i++)
- q->timestamps[i].pts = q->timestamps[i].dts = AV_NOPTS_VALUE;
+ q->timestamps[i].id = -1;
}
int ff_qsv_init(AVCodecContext *c, QSVContext *q)
@@ -132,10 +132,12 @@ int ff_qsv_init(AVCodecContext *c, QSVContext *q)
return ff_qsv_error(ret);
q->nb_timestamps = req.NumFrameSuggested + q->param.AsyncDepth;
- q->put_dts_cnt = 0;
+ q->put_ts_cnt = 0;
q->decoded_cnt = 0;
q->last_ret = MFX_ERR_MORE_DATA;
+ q->timestamp_scale = 90000 * c->time_base.num * c->ticks_per_frame /
c->time_base.den;
+
if (!(q->timestamps = av_mallocz_array(q->nb_timestamps,
sizeof(*q->timestamps))))
return AVERROR(ENOMEM);
@@ -265,56 +267,48 @@ static int realloc_timestamps(QSVContext *q, int
old_nmemb, int new_nmemb)
q->nb_timestamps = new_nmemb;
for (int i = old_nmemb; i < q->nb_timestamps; i++)
- q->timestamps[i].pts = q->timestamps[i].dts = AV_NOPTS_VALUE;
+ q->timestamps[i].id = -1;
return 0;
}
-static int get_dts(QSVContext *q, int64_t pts, int64_t *dts)
+static int get_ts(QSVContext *q, int64_t id, int64_t *pts, int64_t *dts)
{
- int i;
-
- if (pts == AV_NOPTS_VALUE) {
- *dts = AV_NOPTS_VALUE;
- return 0;
- }
+ int i = id % q->nb_timestamps;
- for (i = 0; i < q->nb_timestamps; i++) {
- if (q->timestamps[i].pts == pts)
- break;
- }
- if (i == q->nb_timestamps) {
+ if (id >= q->put_ts_cnt || id < 0 || q->timestamps[i].id != id) {
av_log(q, AV_LOG_ERROR,
- "Requested pts %"PRId64" does not match any dts\n",
- pts);
+ "Requested timestamp of %"PRId64" th is not found\n",
+ id);
return AVERROR_BUG;
}
- *dts = q->timestamps[i].dts;
- q->timestamps[i].pts = AV_NOPTS_VALUE;
+ *pts = q->timestamps[i].pts;
+ *dts = q->timestamps[i].dts;
return 0;
}
-static int put_dts(QSVContext *q, int64_t pts, int64_t dts)
+static int put_ts(QSVContext *q, int64_t pts, int64_t dts, int64_t *id)
{
int ret, i;
- if (!q->decoded_cnt && q->nb_timestamps == q->put_dts_cnt) {
+ if (!q->decoded_cnt && q->nb_timestamps == q->put_ts_cnt) {
// For decoder delay
if ((ret = realloc_timestamps(q, q->nb_timestamps, q->nb_timestamps *
2)) < 0)
return ret;
- } else if (q->decoded_cnt == 1 && q->nb_timestamps < (q->put_dts_cnt +
32)) {
+ } else if (q->decoded_cnt == 1 && q->nb_timestamps < (q->put_ts_cnt + 32))
{
// For frame reordering
// I[31]P[30]B[29]B[28] ... B[1]B[0] (Number in [] is display order)
- if ((ret = realloc_timestamps(q, q->nb_timestamps, q->put_dts_cnt +
32)) < 0)
+ if ((ret = realloc_timestamps(q, q->nb_timestamps, q->put_ts_cnt +
32)) < 0)
return ret;
}
- i = q->put_dts_cnt % q->nb_timestamps;
+ i = q->put_ts_cnt % q->nb_timestamps;
+ q->timestamps[i].id = *id = q->put_ts_cnt;
q->timestamps[i].pts = pts;
q->timestamps[i].dts = dts;
- q->put_dts_cnt++;
+ q->put_ts_cnt++;
return 0;
}
@@ -330,6 +324,7 @@ int ff_qsv_decode(AVCodecContext *avctx, QSVContext *q,
int size = avpkt->size;
int busymsec = 0;
int ret;
+ int64_t timestamp_id;
*got_frame = 0;
@@ -346,8 +341,8 @@ int ff_qsv_decode(AVCodecContext *avctx, QSVContext *q,
ff_packet_list_get(&q->pending, &q->pending_end, &pkt);
- if (!(ret = put_dts(q, pkt.pts, pkt.dts))) {
- q->bs.TimeStamp = pkt.pts;
+ if (!(ret = put_ts(q, pkt.pts, pkt.dts, ×tamp_id))) {
+ q->bs.TimeStamp = timestamp_id * q->timestamp_scale;
ret = bitstream_enqueue(&q->bs, pkt.data, pkt.size);
}
@@ -401,12 +396,13 @@ int ff_qsv_decode(AVCodecContext *avctx, QSVContext *q,
}
if (sync) {
- int64_t dts;
+ int64_t pts, dts;
AVFrame *workframe;
MFXVideoCORE_SyncOperation(q->session, sync, 60000);
- if ((ret = get_dts(q, outsurf->Data.TimeStamp, &dts)) < 0)
+ timestamp_id = outsurf->Data.TimeStamp / q->timestamp_scale;
+ if ((ret = get_ts(q, timestamp_id, &pts, &dts)) < 0)
return ret;
workframe = outsurf->Data.MemId;
@@ -419,8 +415,9 @@ int ff_qsv_decode(AVCodecContext *avctx, QSVContext *q,
outsurf->Data.UV = workframe->data[1];
*got_frame = 1;
+ q->decoded_cnt++;
- frame->pkt_pts = frame->pts = outsurf->Data.TimeStamp;
+ frame->pkt_pts = frame->pts = pts;
frame->pkt_dts = dts;
frame->repeat_pict =
diff --git a/libavcodec/qsv.h b/libavcodec/qsv.h
index dd2a53d..555edd5 100644
--- a/libavcodec/qsv.h
+++ b/libavcodec/qsv.h
@@ -38,6 +38,7 @@
typedef struct QSVTimeStamp {
+ int64_t id;
int64_t pts;
int64_t dts;
} QSVTimeStamp;
@@ -54,7 +55,8 @@ typedef struct QSVContext {
QSVSurfaceList *surflist;
QSVTimeStamp *timestamps;
int nb_timestamps;
- int put_dts_cnt;
+ int timestamp_scale;
+ int put_ts_cnt;
int decoded_cnt;
mfxSyncPoint sync;
mfxBitstream bs;
--
1.8.3.msysgit.0
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel