if (avctx->pkt_timebase.num && avctx->pkt_timebase.den) {
frame->pts = av_rescale_q(info->presentationTimeUs,
- av_make_q(1, 1000000),
+ AV_TIME_BASE_Q,
avctx->pkt_timebase);
} else {
frame->pts = info->presentationTimeUs;
* * 0-sized avpackets are pushed to flush remaining frames at EOS */
if (avctx->pkt_timebase.num && avctx->pkt_timebase.den) {
frame->pts = av_rescale_q(info->presentationTimeUs,
- av_make_q(1, 1000000),
+ AV_TIME_BASE_Q,
avctx->pkt_timebase);
} else {
frame->pts = info->presentationTimeUs;
av_log(avctx, AV_LOG_TRACE,
"Frame: width=%d stride=%d height=%d slice-height=%d "
- "crop-top=%d crop-bottom=%d crop-left=%d crop-right=%d encoder=%s\n"
+ "crop-top=%d crop-bottom=%d crop-left=%d crop-right=%d encoder=%s "
"destination linesizes=%d,%d,%d\n" ,
avctx->width, s->stride, avctx->height, s->slice_height,
s->crop_top, s->crop_bottom, s->crop_left, s->crop_right, s->codec_name,
s->stride = s->stride > 0 ? s->stride : s->width;
AMEDIAFORMAT_GET_INT32(s->slice_height, "slice-height", 0);
- s->slice_height = s->slice_height > 0 ? s->slice_height : s->height;
- if (strstr(s->codec_name, "OMX.Nvidia.")) {
+ if (strstr(s->codec_name, "OMX.Nvidia.") && s->slice_height == 0) {
s->slice_height = FFALIGN(s->height, 16);
} else if (strstr(s->codec_name, "OMX.SEC.avc.dec")) {
s->slice_height = avctx->height;
s->stride = avctx->width;
+ } else if (s->slice_height == 0) {
+ s->slice_height = s->height;
}
AMEDIAFORMAT_GET_INT32(s->color_format, "color-format", 1);
s->eos = 0;
atomic_fetch_add(&s->serial, 1);
atomic_init(&s->hw_buffer_count, 0);
+ s->current_input_buffer = -1;
status = ff_AMediaCodec_flush(codec);
if (status < 0) {
atomic_init(&s->refcount, 1);
atomic_init(&s->hw_buffer_count, 0);
atomic_init(&s->serial, 1);
+ s->current_input_buffer = -1;
pix_fmt = ff_get_format(avctx, pix_fmts);
if (pix_fmt == AV_PIX_FMT_MEDIACODEC) {
}
int ff_mediacodec_dec_send(AVCodecContext *avctx, MediaCodecDecContext *s,
- AVPacket *pkt)
+ AVPacket *pkt, bool wait)
{
int offset = 0;
int need_draining = 0;
uint8_t *data;
- ssize_t index;
+ ssize_t index = s->current_input_buffer;
size_t size;
FFAMediaCodec *codec = s->codec;
int status;
- int64_t input_dequeue_timeout_us = INPUT_DEQUEUE_TIMEOUT_US;
+ int64_t input_dequeue_timeout_us = wait ? INPUT_DEQUEUE_TIMEOUT_US : 0;
+ int64_t pts;
if (s->flushing) {
av_log(avctx, AV_LOG_ERROR, "Decoder is flushing and cannot accept new buffer "
}
while (offset < pkt->size || (need_draining && !s->draining)) {
-
- index = ff_AMediaCodec_dequeueInputBuffer(codec, input_dequeue_timeout_us);
- if (ff_AMediaCodec_infoTryAgainLater(codec, index)) {
- av_log(avctx, AV_LOG_TRACE, "No input buffer available, try again later\n");
- break;
- }
-
if (index < 0) {
- av_log(avctx, AV_LOG_ERROR, "Failed to dequeue input buffer (status=%zd)\n", index);
- return AVERROR_EXTERNAL;
+ index = ff_AMediaCodec_dequeueInputBuffer(codec, input_dequeue_timeout_us);
+ if (ff_AMediaCodec_infoTryAgainLater(codec, index)) {
+ av_log(avctx, AV_LOG_TRACE, "No input buffer available, try again later\n");
+ break;
+ }
+
+ if (index < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to dequeue input buffer (status=%zd)\n", index);
+ return AVERROR_EXTERNAL;
+ }
}
+ s->current_input_buffer = -1;
data = ff_AMediaCodec_getInputBuffer(codec, index, &size);
if (!data) {
return AVERROR_EXTERNAL;
}
+ pts = pkt->pts;
+ if (pts != AV_NOPTS_VALUE && avctx->pkt_timebase.num && avctx->pkt_timebase.den) {
+ pts = av_rescale_q(pts, avctx->pkt_timebase, AV_TIME_BASE_Q);
+ }
+
if (need_draining) {
- int64_t pts = pkt->pts;
uint32_t flags = ff_AMediaCodec_getBufferFlagEndOfStream(codec);
- if (s->surface) {
- pts = av_rescale_q(pts, avctx->pkt_timebase, av_make_q(1, 1000000));
- }
-
av_log(avctx, AV_LOG_DEBUG, "Sending End Of Stream signal\n");
status = ff_AMediaCodec_queueInputBuffer(codec, index, 0, 0, pts, flags);
"Queued input buffer %zd size=%zd ts=%"PRIi64"\n", index, size, pts);
s->draining = 1;
- break;
- } else {
- int64_t pts = pkt->pts;
-
- size = FFMIN(pkt->size - offset, size);
- memcpy(data, pkt->data + offset, size);
- offset += size;
-
- if (avctx->pkt_timebase.num && avctx->pkt_timebase.den) {
- pts = av_rescale_q(pts, avctx->pkt_timebase, av_make_q(1, 1000000));
- }
+ return 0;
+ }
- status = ff_AMediaCodec_queueInputBuffer(codec, index, 0, size, pts, 0);
- if (status < 0) {
- av_log(avctx, AV_LOG_ERROR, "Failed to queue input buffer (status = %d)\n", status);
- return AVERROR_EXTERNAL;
- }
+ size = FFMIN(pkt->size - offset, size);
+ memcpy(data, pkt->data + offset, size);
+ offset += size;
- av_log(avctx, AV_LOG_TRACE,
- "Queued input buffer %zd size=%zd ts=%"PRIi64"\n", index, size, pts);
+ status = ff_AMediaCodec_queueInputBuffer(codec, index, 0, size, pts, 0);
+ if (status < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to queue input buffer (status = %d)\n", status);
+ return AVERROR_EXTERNAL;
}
+
+ av_log(avctx, AV_LOG_TRACE,
+ "Queued input buffer %zd size=%zd ts=%"PRIi64"\n", index, size, pts);
}
if (offset == 0)
return AVERROR(EAGAIN);
}
+/*
+* ff_mediacodec_dec_flush returns 0 if the flush cannot be performed on
+* the codec (because the user retains frames). The codec stays in the
+* flushing state.
+*
+* ff_mediacodec_dec_flush returns 1 if the flush can actually be
+* performed on the codec. The codec leaves the flushing state and can
+* process again packets.
+*
+* ff_mediacodec_dec_flush returns a negative value if an error has
+* occurred.
+*/
int ff_mediacodec_dec_flush(AVCodecContext *avctx, MediaCodecDecContext *s)
{
if (!s->surface || atomic_load(&s->refcount) == 1) {