[FFmpeg-devel] [PATCH 2/2] crystalhd: Use mpeg4_unpack_bframes to avoid buggy crystalhd handling
Philip Langdale
philipl at overt.org
Sun Oct 9 20:50:13 EEST 2016
The hardware handling of packed bframes was always questionable but
it used to ok with my workaround. Today, not so much. But today we
have a bsf to unpack the bframes, so let's just use that and be
done with it.
---
libavcodec/crystalhd.c | 127 ++++++++++++++++++++++++-------------------------
1 file changed, 63 insertions(+), 64 deletions(-)
diff --git a/libavcodec/crystalhd.c b/libavcodec/crystalhd.c
index 83be8e5..9120940 100644
--- a/libavcodec/crystalhd.c
+++ b/libavcodec/crystalhd.c
@@ -150,7 +150,6 @@ typedef struct {
/* Options */
uint32_t sWidth;
- uint8_t bframe_bug;
} CHDContext;
static const AVOption options[] = {
@@ -379,9 +378,59 @@ static av_cold int uninit(AVCodecContext *avctx)
}
+static av_cold int init_bsf(AVCodecContext *avctx, const char *bsf_name)
+{
+ CHDContext *priv = avctx->priv_data;
+ const AVBitStreamFilter *bsf;
+ int avret;
+ void *extradata = NULL;
+ size_t size = 0;
+
+ bsf = av_bsf_get_by_name(bsf_name);
+ if (!bsf) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Cannot open the %s BSF!\n", bsf_name);
+ return AVERROR_BSF_NOT_FOUND;
+ }
+
+ avret = av_bsf_alloc(bsf, &priv->bsfc);
+ if (avret != 0) {
+ return avret;
+ }
+
+ avret = avcodec_parameters_from_context(priv->bsfc->par_in, avctx);
+ if (avret != 0) {
+ return avret;
+ }
+
+ avret = av_bsf_init(priv->bsfc);
+ if (avret != 0) {
+ return avret;
+ }
+
+ /* Back up the extradata so it can be restored at close time. */
+ priv->orig_extradata = avctx->extradata;
+ priv->orig_extradata_size = avctx->extradata_size;
+
+ size = priv->bsfc->par_out->extradata_size;
+ extradata = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
+ if (!extradata) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Failed to allocate copy of extradata\n");
+ return AVERROR(ENOMEM);
+ }
+ memcpy(extradata, priv->bsfc->par_out->extradata, size);
+
+ avctx->extradata = extradata;
+ avctx->extradata_size = size;
+
+ return 0;
+}
+
static av_cold int init(AVCodecContext *avctx)
{
CHDContext* priv;
+ int avret;
BC_STATUS ret;
BC_INFO_CRYSTAL version;
BC_INPUT_FORMAT format = {
@@ -417,46 +466,22 @@ static av_cold int init(AVCodecContext *avctx)
subtype = id2subtype(priv, avctx->codec->id);
switch (subtype) {
case BC_MSUBTYPE_AVC1:
- {
- const AVBitStreamFilter *bsf;
- int avret;
-
- bsf = av_bsf_get_by_name("h264_mp4toannexb");
- if (!bsf) {
- av_log(avctx, AV_LOG_ERROR,
- "Cannot open the h264_mp4toannexb BSF!\n");
- return AVERROR_BSF_NOT_FOUND;
- }
- avret = av_bsf_alloc(bsf, &priv->bsfc);
- if (avret != 0) {
- return AVERROR(ENOMEM);
- }
- avret = avcodec_parameters_from_context(priv->bsfc->par_in, avctx);
- if (avret != 0) {
- return AVERROR(ENOMEM);
- }
- avret = av_bsf_init(priv->bsfc);
- if (avret != 0) {
- return AVERROR(ENOMEM);
- }
-
- format.metaDataSz = priv->bsfc->par_out->extradata_size;
- format.pMetaData = av_malloc(format.metaDataSz + AV_INPUT_BUFFER_PADDING_SIZE);
- if (!format.pMetaData) {
- av_log(avctx, AV_LOG_ERROR,
- "Failed to allocate copy of extradata\n");
- return AVERROR(ENOMEM);
- }
- memcpy(format.pMetaData, priv->bsfc->par_out->extradata, format.metaDataSz);
-
- /* Back up the extradata so it can be restored at close time. */
- priv->orig_extradata = avctx->extradata;
- priv->orig_extradata_size = avctx->extradata_size;
- avctx->extradata = format.pMetaData;
- avctx->extradata_size = format.metaDataSz;
+ avret = init_bsf(avctx, "h264_mp4toannexb");
+ if (avret != 0) {
+ return avret;
}
subtype = BC_MSUBTYPE_H264;
format.startCodeSz = 4;
+ format.pMetaData = avctx->extradata;
+ format.metaDataSz = avctx->extradata_size;
+ break;
+ case BC_MSUBTYPE_DIVX:
+ avret = init_bsf(avctx, "mpeg4_unpack_bframes");
+ if (avret != 0) {
+ return avret;
+ }
+ format.pMetaData = avctx->extradata;
+ format.metaDataSz = avctx->extradata_size;
break;
case BC_MSUBTYPE_H264:
format.startCodeSz = 4;
@@ -466,7 +491,6 @@ static av_cold int init(AVCodecContext *avctx)
case BC_MSUBTYPE_WMV3:
case BC_MSUBTYPE_WMVA:
case BC_MSUBTYPE_MPEG2VIDEO:
- case BC_MSUBTYPE_DIVX:
case BC_MSUBTYPE_DIVX311:
format.pMetaData = avctx->extradata;
format.metaDataSz = avctx->extradata_size;
@@ -839,15 +863,6 @@ static inline CopyRet receive_frame(AVCodecContext *avctx,
priv->last_picture = output.PicInfo.picture_number - 1;
}
- if (avctx->codec->id == AV_CODEC_ID_MPEG4 &&
- output.PicInfo.timeStamp == 0 && priv->bframe_bug) {
- av_log(avctx, AV_LOG_VERBOSE,
- "CrystalHD: Not returning packed frame twice.\n");
- priv->last_picture++;
- DtsReleaseOutputBuffs(dev, NULL, FALSE);
- return RET_COPY_AGAIN;
- }
-
print_frame_info(priv, &output);
if (priv->last_picture + 1 < output.PicInfo.picture_number) {
@@ -908,22 +923,6 @@ static int decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *a
av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: decode_frame\n");
- if (avpkt->size == 7 && !priv->bframe_bug) {
- /*
- * The use of a drop frame triggers the bug
- */
- av_log(avctx, AV_LOG_INFO,
- "CrystalHD: Enabling work-around for packed b-frame bug\n");
- priv->bframe_bug = 1;
- } else if (avpkt->size == 8 && priv->bframe_bug) {
- /*
- * Delay frames don't trigger the bug
- */
- av_log(avctx, AV_LOG_INFO,
- "CrystalHD: Disabling work-around for packed b-frame bug\n");
- priv->bframe_bug = 0;
- }
-
if (len) {
int32_t tx_free = (int32_t)DtsTxFreeSize(dev);
--
2.7.4
More information about the ffmpeg-devel
mailing list