summaryrefslogtreecommitdiff
path: root/libavcodec/crystalhd.c
diff options
context:
space:
mode:
authorPhilip Langdale <philipl@overt.org>2016-10-11 20:17:06 -0700
committerPhilip Langdale <philipl@overt.org>2016-11-02 13:47:57 -0700
commit3019b4f6480a5d8c38e0e32ef75dabe6e0f3ae98 (patch)
tree95bb134203f12f1e7bfa18cc17f743bc1c4ce50f /libavcodec/crystalhd.c
parent0eb836942f5d6ff803e0374156ca21544e926e7c (diff)
crystalhd: Loop for a frame internally where possible.
It's not possible to return EAGAIN when we've passed input EOF and are in draining mode. If do return EAGAIN, we're saying there's no way to get any more output - which isn't true in many cases. So let's handled these cases in an internal loop as best we can.
Diffstat (limited to 'libavcodec/crystalhd.c')
-rw-r--r--libavcodec/crystalhd.c40
1 files changed, 26 insertions, 14 deletions
diff --git a/libavcodec/crystalhd.c b/libavcodec/crystalhd.c
index 4ac138cb2e..2d803ab46a 100644
--- a/libavcodec/crystalhd.c
+++ b/libavcodec/crystalhd.c
@@ -105,6 +105,7 @@
typedef enum {
RET_ERROR = -1,
RET_OK = 0,
+ RET_COPY_AGAIN = 1,
} CopyRet;
typedef struct OpaqueList {
@@ -129,6 +130,7 @@ typedef struct {
uint32_t sps_pps_size;
uint8_t is_nal;
uint8_t need_second_field;
+ uint8_t draining;
OpaqueList *head;
OpaqueList *tail;
@@ -304,6 +306,7 @@ static void flush(AVCodecContext *avctx)
CHDContext *priv = avctx->priv_data;
priv->need_second_field = 0;
+ priv->draining = 0;
av_frame_unref (priv->pic);
@@ -438,6 +441,7 @@ static av_cold int init(AVCodecContext *avctx)
priv->avctx = avctx;
priv->is_nal = avctx->extradata_size > 0 && *(avctx->extradata) == 1;
priv->pic = av_frame_alloc();
+ priv->draining = 0;
subtype = id2subtype(priv, avctx->codec->id);
switch (subtype) {
@@ -670,6 +674,8 @@ FF_ENABLE_DEPRECATION_WARNINGS
if ((ret = av_frame_ref(data, priv->pic)) < 0) {
return ret;
}
+ } else {
+ return RET_COPY_AGAIN;
}
return RET_OK;
@@ -745,7 +751,7 @@ static inline CopyRet receive_frame(AVCodecContext *avctx,
avctx->sample_aspect_ratio = (AVRational) {221, 1};
break;
}
- return RET_OK;
+ return RET_COPY_AGAIN;
} else if (ret == BC_STS_SUCCESS) {
int copy_ret = -1;
if (output.PoutFlags & BC_POUT_FLAGS_PIB_VALID) {
@@ -768,13 +774,13 @@ static inline CopyRet receive_frame(AVCodecContext *avctx,
*/
av_log(avctx, AV_LOG_ERROR, "CrystalHD: ProcOutput succeeded with "
"invalid PIB\n");
- copy_ret = RET_OK;
+ copy_ret = RET_COPY_AGAIN;
}
DtsReleaseOutputBuffs(dev, NULL, FALSE);
return copy_ret;
} else if (ret == BC_STS_BUSY) {
- return RET_OK;
+ return RET_COPY_AGAIN;
} else {
av_log(avctx, AV_LOG_ERROR, "CrystalHD: ProcOutput failed %d\n", ret);
return RET_ERROR;
@@ -874,6 +880,7 @@ static int crystalhd_decode_packet(AVCodecContext *avctx, const AVPacket *avpkt)
}
} else {
av_log(avctx, AV_LOG_INFO, "CrystalHD: No more input data\n");
+ priv->draining = 1;
ret = AVERROR_EOF;
goto exit;
}
@@ -893,22 +900,27 @@ static int crystalhd_receive_frame(AVCodecContext *avctx, AVFrame *frame)
av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: receive_frame\n");
- bc_ret = DtsGetDriverStatus(dev, &decoder_status);
- if (bc_ret != BC_STS_SUCCESS) {
- av_log(avctx, AV_LOG_ERROR, "CrystalHD: GetDriverStatus failed\n");
- return -1;
- }
+ do {
+ bc_ret = DtsGetDriverStatus(dev, &decoder_status);
+ if (bc_ret != BC_STS_SUCCESS) {
+ av_log(avctx, AV_LOG_ERROR, "CrystalHD: GetDriverStatus failed\n");
+ return -1;
+ }
- if (decoder_status.ReadyListCount == 0) {
- av_log(avctx, AV_LOG_INFO, "CrystalHD: Insufficient frames ready. Returning\n");
- return AVERROR(EAGAIN);
- }
+ if (decoder_status.ReadyListCount == 0) {
+ av_log(avctx, AV_LOG_INFO, "CrystalHD: Insufficient frames ready. Returning\n");
+ got_frame = 0;
+ rec_ret = RET_OK;
+ break;
+ }
+
+ rec_ret = receive_frame(avctx, frame, &got_frame);
+ } while (rec_ret == RET_COPY_AGAIN);
- rec_ret = receive_frame(avctx, frame, &got_frame);
if (rec_ret == RET_ERROR) {
return -1;
} else if (got_frame == 0) {
- return AVERROR(EAGAIN);
+ return priv->draining ? AVERROR_EOF : AVERROR(EAGAIN);
} else {
return 0;
}