[FFmpeg-devel] [PATCH 3/7] CrystalHD: Handle different h.264 MBAFF packing.
Philip Langdale
philipl at overt.org
Sat Mar 26 18:50:45 CET 2011
I found another MBAFF sample where the input:output pattern is
the same as mpeg2 and vc1 (fieldpair input, individual field output).
While I'm not sure how you can output individual fields from MBAFF,
if I apply the mpeg2/vc1 handling to this file, it plays correctly.
So, this changes the detection algorithm to handle the known cases.
Signed-off-by: Philip Langdale <philipl at overt.org>
---
libavcodec/crystalhd.c | 79 +++++++++++++++++++++++++----------------------
1 files changed, 42 insertions(+), 37 deletions(-)
diff --git a/libavcodec/crystalhd.c b/libavcodec/crystalhd.c
index 3f66b96..95fe931 100644
--- a/libavcodec/crystalhd.c
+++ b/libavcodec/crystalhd.c
@@ -102,10 +102,11 @@
****************************************************************************/
typedef enum {
- RET_ERROR = -1,
- RET_OK = 0,
- RET_COPY_AGAIN = 1,
- RET_SKIP_NEXT_COPY = 2,
+ RET_ERROR = -1,
+ RET_OK = 0,
+ RET_COPY_AGAIN = 1,
+ RET_SKIP_NEXT_COPY = 2,
+ RET_COPY_NEXT_FIELD = 3,
} CopyRet;
typedef struct OpaqueList {
@@ -624,7 +625,13 @@ static inline CopyRet copy_frame(AVCodecContext *avctx,
return RET_SKIP_NEXT_COPY;
}
- return RET_OK;
+ /*
+ * Testing has shown that in all cases where we don't want to return the
+ * full frame immediately, VDEC_FLAG_UNKNOWN_SRC is set.
+ */
+ return priv->need_second_field &&
+ !(output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) ?
+ RET_COPY_NEXT_FIELD : RET_OK;
}
@@ -806,40 +813,38 @@ static int decode(AVCodecContext *avctx, void *data, int *data_size, AVPacket *a
do {
rec_ret = receive_frame(avctx, data, data_size, 0);
- if (rec_ret == 0 && *data_size == 0) {
- if (avctx->codec->id == CODEC_ID_H264) {
- /*
- * This case is for when the encoded fields are stored
- * separately and we get a separate avpkt for each one. To keep
- * the pipeline stable, we should return nothing and wait for
- * the next time round to grab the second field.
- * H.264 PAFF is an example of this.
- */
- av_log(avctx, AV_LOG_VERBOSE, "Returning after first field.\n");
- avctx->has_b_frames--;
- } else {
- /*
- * This case is for when the encoded fields are stored in a
- * single avpkt but the hardware returns then separately. Unless
- * we grab the second field before returning, we'll slip another
- * frame in the pipeline and if that happens a lot, we're sunk.
- * So we have to get that second field now.
- * Interlaced mpeg2 and vc1 are examples of this.
- */
- av_log(avctx, AV_LOG_VERBOSE, "Trying to get second field.\n");
- while (1) {
- usleep(priv->decode_wait);
- ret = DtsGetDriverStatus(dev, &decoder_status);
- if (ret == BC_STS_SUCCESS &&
- decoder_status.ReadyListCount > 0) {
- rec_ret = receive_frame(avctx, data, data_size, 1);
- if ((rec_ret == 0 && *data_size > 0) ||
- rec_ret == RET_ERROR)
- break;
- }
+ if (rec_ret == RET_OK && *data_size == 0) {
+ /*
+ * This case is for when the encoded fields are stored
+ * separately and we get a separate avpkt for each one. To keep
+ * the pipeline stable, we should return nothing and wait for
+ * the next time round to grab the second field.
+ * H.264 PAFF is an example of this.
+ */
+ av_log(avctx, AV_LOG_VERBOSE, "Returning after first field.\n");
+ avctx->has_b_frames--;
+ } else if (rec_ret == RET_COPY_NEXT_FIELD) {
+ /*
+ * This case is for when the encoded fields are stored in a
+ * single avpkt but the hardware returns then separately. Unless
+ * we grab the second field before returning, we'll slip another
+ * frame in the pipeline and if that happens a lot, we're sunk.
+ * So we have to get that second field now.
+ * Interlaced mpeg2 and vc1 are examples of this.
+ */
+ av_log(avctx, AV_LOG_VERBOSE, "Trying to get second field.\n");
+ while (1) {
+ usleep(priv->decode_wait);
+ ret = DtsGetDriverStatus(dev, &decoder_status);
+ if (ret == BC_STS_SUCCESS &&
+ decoder_status.ReadyListCount > 0) {
+ rec_ret = receive_frame(avctx, data, data_size, 1);
+ if ((rec_ret == RET_OK && *data_size > 0) ||
+ rec_ret == RET_ERROR)
+ break;
}
- av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Got second field.\n");
}
+ av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Got second field.\n");
} else if (rec_ret == RET_SKIP_NEXT_COPY) {
/*
* Two input packets got turned into a field pair. Gawd.
--
1.7.1
More information about the ffmpeg-devel
mailing list