[FFmpeg-devel] [PATCH] CrystalHD decoder support v4
Benoit Fouet
benoit.fouet
Tue Feb 8 09:56:30 CET 2011
Hi,
mostly minor remarks. But I think you should now wait for experts to
comment before bothering sending another patch.
On Sun, 06 Feb 2011 16:56:36 -0700 Philip Langdale wrote:
> diff --git a/libavcodec/crystalhd.c b/libavcodec/crystalhd.c
> new file mode 100644
> index 0000000..b17cb81
> --- /dev/null
> +++ b/libavcodec/crystalhd.c
> @@ -0,0 +1,852 @@
> +/*****************************************************************************
> + * Helper functions
> + ****************************************************************************/
> +
> +static inline uint8_t id2subtype(CHDContext *priv, enum CodecID id)
> +{
This should be BC_MEDIA_SUBTYPE, not uint8_t
> +/*
> + * The OpaqueList is built in decode order, while elements will be removed
> + * in presentation order. If frames are reordered, this means we must be
> + * able to remove elements that are not the first element.
> + */
> +static uint64_t opaque_list_pop(CHDContext *priv, uint64_t fake_timestamp)
> +{
> + OpaqueList *node = priv->head;
> +
OK, this could be done with "OpaqueList **node = &priv->head" to avoid
the special case; not sure this is really worth it though.
> +static av_cold int init(AVCodecContext *avctx)
> +{
> + CHDContext* priv;
> + BC_STATUS ret;
> + BC_INPUT_FORMAT format = {
> + .FGTEnable = FALSE,
> + .Progressive = TRUE,
> + .OptFlags = 0x80000000 | vdecFrameRate59_94 | 0x40,
> + .width = avctx->width,
> + .height = avctx->height,
> + };
> +
> + uint8_t subtype;
> +
BC_MEDIA_SUBTYPE? Maybe even use format.mSubtype directly?
> + case BC_MSUBTYPE_AVC1:
> + {
> + uint8_t *dummy_p;
> + int dummy_int;
> + AVBitStreamFilterContext *bsfc;
> +
> + uint32_t orig_data_size = avctx->extradata_size;
> + uint8_t *orig_data = av_malloc(orig_data_size);
> + if (!orig_data) {
> + av_log(avctx, AV_LOG_ERROR,
> + "Failed to allocate copy of extradata\n");
> + return AVERROR(ENOMEM);
> + }
> + memcpy(orig_data, avctx->extradata, orig_data_size);
> +
> +
> + bsfc= av_bitstream_filter_init("h264_mp4toannexb");
> + if (!bsfc) {
> + av_log(avctx, AV_LOG_ERROR,
> + "Cannot open the h264_mp4toannexb BSF!\n");
missing "av_free(orig_data);"
> + return AVERROR_BSF_NOT_FOUND;
> + }
> + av_bitstream_filter_filter(bsfc, avctx, NULL, &dummy_p,
> + &dummy_int, NULL, 0, 0);
you should check the error code here.
> + av_bitstream_filter_close(bsfc);
> +
> + priv->sps_pps_buf = avctx->extradata;
> + priv->sps_pps_size = avctx->extradata_size;
> + avctx->extradata = orig_data;
> + avctx->extradata_size = orig_data_size;
> +
> + format.pMetaData = priv->sps_pps_buf;
> + format.metaDataSz = priv->sps_pps_size;
> + format.startCodeSz = (avctx->extradata[4] & 0x03) + 1;
> + }
> + break;
> + case BC_MSUBTYPE_H264:
> + format.startCodeSz = 4;
> + // Fall-through
> + case BC_MSUBTYPE_VC1:
> + case BC_MSUBTYPE_WVC1:
> + case BC_MSUBTYPE_WMV3:
> + case BC_MSUBTYPE_WMVA:
> + case BC_MSUBTYPE_MPEG1VIDEO:
> + case BC_MSUBTYPE_MPEG2VIDEO:
> + case BC_MSUBTYPE_DIVX:
> + case BC_MSUBTYPE_DIVX311:
> + format.pMetaData = avctx->extradata;
> + format.metaDataSz = avctx->extradata_size;
> + break;
> + default:
> + av_log(avctx, AV_LOG_ERROR, "CrystalHD: Unknown codec name\n");
> + return -1;
EINVAL?
> + }
> + format.mSubtype = subtype;
> +
> + /* Get a decoder instance */
> + av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: starting up\n");
> + // Initialize the Link and Decoder devices
> + ret = DtsDeviceOpen(&priv->dev, mode);
> + if (ret != BC_STS_SUCCESS) {
> + av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: DtsDeviceOpen failed\n");
> + uninit(avctx);
> + return -1;
maybe an error label with this uninit+return pattern could be added.
also, this -1 should be changed to a "real" error code.
> +static inline CopyRet copy_frame(AVCodecContext *avctx,
> + BC_DTS_PROC_OUT *output,
> + void *data, int *data_size,
> + uint8_t second_field)
> +{
> + BC_STATUS ret;
> + BC_DTS_STATUS decoder_status;
> + uint8_t next_frame_same;
> + uint8_t interlaced;
> + uint8_t need_second_field;
> +
> + CHDContext *priv = avctx->priv_data;
> +
> + uint8_t bottom_field = (output->PicInfo.flags & VDEC_FLAG_BOTTOMFIELD) ==
> + VDEC_FLAG_BOTTOMFIELD;
> + uint8_t bottom_first = !!(output->PicInfo.flags & VDEC_FLAG_BOTTOM_FIRST);
> +
> + int width = output->PicInfo.width * 2; // 16bits per pixel for YUYV
> + int height = output->PicInfo.height;
> + uint8_t *src = output->Ybuff;
> + uint8_t *dst;
> + int dStride;
> +
> + ret = DtsGetDriverStatus(priv->dev, &decoder_status);
> + if (ret != BC_STS_SUCCESS) {
> + av_log(avctx, AV_LOG_ERROR,
> + "CrystalHD: GetDriverStatus failed: %u\n", ret);
> + return RET_ERROR;
> + }
> +
> + next_frame_same = output->PicInfo.picture_number ==
> + (decoder_status.picNumFlags & ~0x40000000);
> + interlaced = ((output->PicInfo.flags & VDEC_FLAG_INTERLACED_SRC) &&
> + !(output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC)) ||
> + next_frame_same || bottom_field || second_field;
> + need_second_field = interlaced && (!bottom_field == !bottom_first);
> +
as bottom_field and bottom_first are boolean now, the second part can
be simplified to bottom_field == bottom_first.
> +static inline CopyRet receive_frame(AVCodecContext *avctx,
> + void *data, int *data_size,
> + uint8_t second_field)
> +{
> + BC_STATUS ret;
> + BC_DTS_PROC_OUT output = {
> + .PicInfo.width = avctx->width,
> + .PicInfo.height = avctx->height,
> + };
> + CHDContext *priv = avctx->priv_data;
> + HANDLE dev = priv->dev;
> +
> + *data_size = 0;
> +
> + // Request decoded data from the driver
> + ret = DtsProcOutputNoCopy(dev, OUTPUT_PROC_TIMEOUT, &output);
> + if (ret == BC_STS_FMT_CHANGE) {
> + av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Initial format change\n");
> + avctx->width = output.PicInfo.width;
> + avctx->height = output.PicInfo.height;
> + return RET_COPY_AGAIN;
> + } else if (ret == BC_STS_SUCCESS) {
It looks strange to me to not have the success case as the first one.
--
Ben
More information about the ffmpeg-devel
mailing list