static enum AVPixelFormat h263_get_format(AVCodecContext *avctx) { if (avctx->codec->id == AV_CODEC_ID_MSS2) return AV_PIX_FMT_YUV420P; return avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts); }
static enum AVPixelFormat h263_get_format(AVCodecContext *avctx) { if (avctx->codec->id == AV_CODEC_ID_MSS2) return AV_PIX_FMT_YUV420P; if (CONFIG_GRAY && (avctx->flags & CODEC_FLAG_GRAY)) return AV_PIX_FMT_GRAY8; return avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts); }
static enum AVPixelFormat h263_get_format(AVCodecContext *avctx) { if (avctx->codec->id == AV_CODEC_ID_MSS2) return AV_PIX_FMT_YUV420P; if (CONFIG_GRAY && (avctx->flags & AV_CODEC_FLAG_GRAY)) { if (avctx->color_range == AVCOL_RANGE_UNSPECIFIED) avctx->color_range = AVCOL_RANGE_MPEG; return AV_PIX_FMT_GRAY8; } return avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts); }
static enum AVPixelFormat h263_get_format(AVCodecContext *avctx) { /* MPEG-4 Studio Profile only, not supported by hardware */ if (avctx->bits_per_raw_sample > 8) { av_assert1(((MpegEncContext *)avctx->priv_data)->studio_profile); return avctx->pix_fmt; } if (avctx->codec->id == AV_CODEC_ID_MSS2) return AV_PIX_FMT_YUV420P; if (CONFIG_GRAY && (avctx->flags & AV_CODEC_FLAG_GRAY)) { if (avctx->color_range == AVCOL_RANGE_UNSPECIFIED) avctx->color_range = AVCOL_RANGE_MPEG; return AV_PIX_FMT_GRAY8; } return avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts); }
static av_cold int decode_init(AVCodecContext *avctx) { EightBpsContext * const c = avctx->priv_data; c->avctx = avctx; switch (avctx->bits_per_coded_sample) { case 8: avctx->pix_fmt = AV_PIX_FMT_PAL8; c->planes = 1; c->planemap[0] = 0; // 1st plane is palette indexes break; case 24: avctx->pix_fmt = ff_get_format(avctx, pixfmt_rgb24); c->planes = 3; c->planemap[0] = 2; // 1st plane is red c->planemap[1] = 1; // 2nd plane is green c->planemap[2] = 0; // 3rd plane is blue break; case 32: avctx->pix_fmt = AV_PIX_FMT_RGB32; c->planes = 4; /* handle planemap setup later for decoding rgb24 data as rbg32 */ break; default: av_log(avctx, AV_LOG_ERROR, "Error: Unsupported color depth: %u.\n", avctx->bits_per_coded_sample); return AVERROR_INVALIDDATA; } if (avctx->pix_fmt == AV_PIX_FMT_RGB32) { c->planemap[0] = HAVE_BIGENDIAN ? 1 : 2; // 1st plane is red c->planemap[1] = HAVE_BIGENDIAN ? 2 : 1; // 2nd plane is green c->planemap[2] = HAVE_BIGENDIAN ? 3 : 0; // 3rd plane is blue c->planemap[3] = HAVE_BIGENDIAN ? 0 : 3; // 4th plane is alpha } return 0; }
static av_cold int ffmmal_init_decoder(AVCodecContext *avctx) { MMALDecodeContext *ctx = avctx->priv_data; MMAL_STATUS_T status; MMAL_ES_FORMAT_T *format_in; MMAL_COMPONENT_T *decoder; char tmp[32]; int ret = 0; bcm_host_init(); if (mmal_vc_init()) { av_log(avctx, AV_LOG_ERROR, "Cannot initialize MMAL VC driver!\n"); return AVERROR(ENOSYS); } if ((ret = ff_get_format(avctx, avctx->codec->pix_fmts)) < 0) return ret; avctx->pix_fmt = ret; if ((status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &ctx->decoder))) goto fail; decoder = ctx->decoder; format_in = decoder->input[0]->format; format_in->type = MMAL_ES_TYPE_VIDEO; switch (avctx->codec_id) { case AV_CODEC_ID_MPEG2VIDEO: format_in->encoding = MMAL_ENCODING_MP2V; break; case AV_CODEC_ID_MPEG4: format_in->encoding = MMAL_ENCODING_MP4V; break; case AV_CODEC_ID_VC1: format_in->encoding = MMAL_ENCODING_WVC1; break; case AV_CODEC_ID_H264: default: format_in->encoding = MMAL_ENCODING_H264; break; } format_in->es->video.width = FFALIGN(avctx->width, 32); format_in->es->video.height = FFALIGN(avctx->height, 16); format_in->es->video.crop.width = avctx->width; format_in->es->video.crop.height = avctx->height; format_in->es->video.frame_rate.num = 24000; format_in->es->video.frame_rate.den = 1001; format_in->es->video.par.num = avctx->sample_aspect_ratio.num; format_in->es->video.par.den = avctx->sample_aspect_ratio.den; format_in->flags = MMAL_ES_FORMAT_FLAG_FRAMED; av_get_codec_tag_string(tmp, sizeof(tmp), format_in->encoding); av_log(avctx, AV_LOG_DEBUG, "Using MMAL %s encoding.\n", tmp); #if HAVE_MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS if (mmal_port_parameter_set_uint32(decoder->input[0], MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS, -1 - ctx->extra_decoder_buffers)) { av_log(avctx, AV_LOG_WARNING, "Could not set input buffering limit.\n"); } #endif if ((status = mmal_port_format_commit(decoder->input[0]))) goto fail; decoder->input[0]->buffer_num = FFMAX(decoder->input[0]->buffer_num_min, 20); decoder->input[0]->buffer_size = FFMAX(decoder->input[0]->buffer_size_min, 512 * 1024); ctx->pool_in = mmal_pool_create(decoder->input[0]->buffer_num, 0); if (!ctx->pool_in) { ret = AVERROR(ENOMEM); goto fail; } if ((ret = ffmal_update_format(avctx)) < 0) goto fail; ctx->queue_decoded_frames = mmal_queue_create(); if (!ctx->queue_decoded_frames) goto fail; decoder->input[0]->userdata = (void*)avctx; decoder->output[0]->userdata = (void*)avctx; decoder->control->userdata = (void*)avctx; if ((status = mmal_port_enable(decoder->control, control_port_cb))) goto fail; if ((status = mmal_port_enable(decoder->input[0], input_callback))) goto fail; if ((status = mmal_port_enable(decoder->output[0], output_callback))) goto fail; if ((status = mmal_component_enable(decoder))) goto fail; return 0; fail: ffmmal_close_decoder(avctx); return ret < 0 ? ret : AVERROR_UNKNOWN; }
int ff_qsv_process_data(AVCodecContext *avctx, QSVContext *q, AVFrame *frame, int *got_frame, AVPacket *pkt) { uint8_t *dummy_data; int dummy_size; int ret; if (!q->avctx_internal) { q->avctx_internal = avcodec_alloc_context3(NULL); if (!q->avctx_internal) return AVERROR(ENOMEM); if (avctx->extradata) { q->avctx_internal->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!q->avctx_internal->extradata) return AVERROR(ENOMEM); memcpy(q->avctx_internal->extradata, avctx->extradata, avctx->extradata_size); q->avctx_internal->extradata_size = avctx->extradata_size; } q->parser = av_parser_init(avctx->codec_id); if (!q->parser) return AVERROR(ENOMEM); q->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; q->orig_pix_fmt = AV_PIX_FMT_NONE; } if (!pkt->size) return qsv_decode(avctx, q, frame, got_frame, pkt); /* we assume the packets are already split properly and want * just the codec parameters here */ av_parser_parse2(q->parser, q->avctx_internal, &dummy_data, &dummy_size, pkt->data, pkt->size, pkt->pts, pkt->dts, pkt->pos); /* TODO: flush delayed frames on reinit */ if (q->parser->format != q->orig_pix_fmt || q->parser->coded_width != avctx->coded_width || q->parser->coded_height != avctx->coded_height) { enum AVPixelFormat pix_fmts[3] = { AV_PIX_FMT_QSV, AV_PIX_FMT_NONE, AV_PIX_FMT_NONE }; enum AVPixelFormat qsv_format; qsv_format = ff_qsv_map_pixfmt(q->parser->format, &q->fourcc); if (qsv_format < 0) { av_log(avctx, AV_LOG_ERROR, "Decoding pixel format '%s' is not supported\n", av_get_pix_fmt_name(q->parser->format)); ret = AVERROR(ENOSYS); goto reinit_fail; } q->orig_pix_fmt = q->parser->format; avctx->pix_fmt = pix_fmts[1] = qsv_format; avctx->width = q->parser->width; avctx->height = q->parser->height; avctx->coded_width = q->parser->coded_width; avctx->coded_height = q->parser->coded_height; avctx->level = q->avctx_internal->level; avctx->profile = q->avctx_internal->profile; ret = ff_get_format(avctx, pix_fmts); if (ret < 0) goto reinit_fail; avctx->pix_fmt = ret; ret = qsv_decode_init(avctx, q); if (ret < 0) goto reinit_fail; } return qsv_decode(avctx, q, frame, got_frame, pkt); reinit_fail: q->orig_pix_fmt = q->parser->format = avctx->pix_fmt = AV_PIX_FMT_NONE; return ret; }
av_cold int ff_h263_decode_init(AVCodecContext *avctx) { MpegEncContext *s = avctx->priv_data; int ret; s->out_format = FMT_H263; // set defaults ff_mpv_decode_defaults(s); ff_mpv_decode_init(s, avctx); s->quant_precision = 5; s->decode_mb = ff_h263_decode_mb; s->low_delay = 1; if (avctx->codec->id == AV_CODEC_ID_MSS2) avctx->pix_fmt = AV_PIX_FMT_YUV420P; else avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts); s->unrestricted_mv = 1; /* select sub codec */ switch (avctx->codec->id) { case AV_CODEC_ID_H263: case AV_CODEC_ID_H263P: s->unrestricted_mv = 0; avctx->chroma_sample_location = AVCHROMA_LOC_CENTER; break; case AV_CODEC_ID_MPEG4: break; case AV_CODEC_ID_MSMPEG4V1: s->h263_pred = 1; s->msmpeg4_version = 1; break; case AV_CODEC_ID_MSMPEG4V2: s->h263_pred = 1; s->msmpeg4_version = 2; break; case AV_CODEC_ID_MSMPEG4V3: s->h263_pred = 1; s->msmpeg4_version = 3; break; case AV_CODEC_ID_WMV1: s->h263_pred = 1; s->msmpeg4_version = 4; break; case AV_CODEC_ID_WMV2: s->h263_pred = 1; s->msmpeg4_version = 5; break; case AV_CODEC_ID_VC1: case AV_CODEC_ID_WMV3: case AV_CODEC_ID_VC1IMAGE: case AV_CODEC_ID_WMV3IMAGE: case AV_CODEC_ID_MSS2: s->h263_pred = 1; s->msmpeg4_version = 6; avctx->chroma_sample_location = AVCHROMA_LOC_LEFT; break; case AV_CODEC_ID_H263I: break; case AV_CODEC_ID_FLV1: s->h263_flv = 1; break; default: av_log(avctx, AV_LOG_ERROR, "Unsupported codec %d\n", avctx->codec->id); return AVERROR(ENOSYS); } s->codec_id = avctx->codec->id; if (avctx->stream_codec_tag == AV_RL32("l263") && avctx->extradata_size == 56 && avctx->extradata[0] == 1) s->ehc_mode = 1; /* for h263, we allocate the images after having read the header */ if (avctx->codec->id != AV_CODEC_ID_H263 && avctx->codec->id != AV_CODEC_ID_H263P && avctx->codec->id != AV_CODEC_ID_MPEG4) { ff_mpv_idct_init(s); if ((ret = ff_mpv_common_init(s)) < 0) return ret; } ff_h263dsp_init(&s->h263dsp); ff_qpeldsp_init(&s->qdsp); ff_h263_decode_init_vlc(); return 0; }
int ff_mediacodec_dec_init(AVCodecContext *avctx, MediaCodecDecContext *s, const char *mime, FFAMediaFormat *format) { int ret = 0; int status; int profile; enum AVPixelFormat pix_fmt; static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_MEDIACODEC, AV_PIX_FMT_NONE, }; s->first_buffer_at = av_gettime(); s->refcount = 1; pix_fmt = ff_get_format(avctx, pix_fmts); if (pix_fmt == AV_PIX_FMT_MEDIACODEC) { AVMediaCodecContext *user_ctx = avctx->hwaccel_context; if (user_ctx && user_ctx->surface) { s->surface = ff_mediacodec_surface_ref(user_ctx->surface, avctx); av_log(avctx, AV_LOG_INFO, "Using surface %p\n", s->surface); } } profile = ff_AMediaCodecProfile_getProfileFromAVCodecContext(avctx); if (profile < 0) { av_log(avctx, AV_LOG_WARNING, "Unsupported or unknown profile"); } s->codec_name = ff_AMediaCodecList_getCodecNameByType(mime, profile, 0, avctx); if (!s->codec_name) { ret = AVERROR_EXTERNAL; goto fail; } av_log(avctx, AV_LOG_DEBUG, "Found decoder %s\n", s->codec_name); s->codec = ff_AMediaCodec_createCodecByName(s->codec_name); if (!s->codec) { av_log(avctx, AV_LOG_ERROR, "Failed to create media decoder for type %s and name %s\n", mime, s->codec_name); ret = AVERROR_EXTERNAL; goto fail; } status = ff_AMediaCodec_configure(s->codec, format, s->surface, NULL, 0); if (status < 0) { char *desc = ff_AMediaFormat_toString(format); av_log(avctx, AV_LOG_ERROR, "Failed to configure codec (status = %d) with format %s\n", status, desc); av_freep(&desc); ret = AVERROR_EXTERNAL; goto fail; } status = ff_AMediaCodec_start(s->codec); if (status < 0) { char *desc = ff_AMediaFormat_toString(format); av_log(avctx, AV_LOG_ERROR, "Failed to start codec (status = %d) with format %s\n", status, desc); av_freep(&desc); ret = AVERROR_EXTERNAL; goto fail; } s->format = ff_AMediaCodec_getOutputFormat(s->codec); if (s->format) { if ((ret = mediacodec_dec_parse_format(avctx, s)) < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to configure context\n"); goto fail; } } av_log(avctx, AV_LOG_DEBUG, "MediaCodec %p started successfully\n", s->codec); return 0; fail: av_log(avctx, AV_LOG_ERROR, "MediaCodec %p failed to start\n", s->codec); ff_mediacodec_dec_close(avctx, s); return ret; }
static av_cold int ffmmal_init_decoder(AVCodecContext *avctx) { MMALDecodeContext *ctx = avctx->priv_data; MMAL_STATUS_T status; MMAL_ES_FORMAT_T *format_in; MMAL_COMPONENT_T *decoder; int ret = 0; bcm_host_init(); if (mmal_vc_init()) { av_log(avctx, AV_LOG_ERROR, "Cannot initialize MMAL VC driver!\n"); return AVERROR(ENOSYS); } if ((ret = ff_get_format(avctx, avctx->codec->pix_fmts)) < 0) return ret; avctx->pix_fmt = ret; if ((status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &ctx->decoder))) goto fail; decoder = ctx->decoder; format_in = decoder->input[0]->format; format_in->type = MMAL_ES_TYPE_VIDEO; format_in->encoding = MMAL_ENCODING_H264; format_in->es->video.width = FFALIGN(avctx->width, 32); format_in->es->video.height = FFALIGN(avctx->height, 16); format_in->es->video.crop.width = avctx->width; format_in->es->video.crop.height = avctx->height; format_in->es->video.frame_rate.num = 24000; format_in->es->video.frame_rate.den = 1001; format_in->es->video.par.num = avctx->sample_aspect_ratio.num; format_in->es->video.par.den = avctx->sample_aspect_ratio.den; format_in->flags = MMAL_ES_FORMAT_FLAG_FRAMED; if (avctx->codec->id == AV_CODEC_ID_H264 && avctx->extradata && avctx->extradata[0] == 1) { uint8_t *dummy_p; int dummy_int; ctx->bsfc = av_bitstream_filter_init("h264_mp4toannexb"); if (!ctx->bsfc) { av_log(avctx, AV_LOG_ERROR, "Cannot open the h264_mp4toannexb BSF!\n"); ret = AVERROR(ENOSYS); goto fail; } av_bitstream_filter_filter(ctx->bsfc, avctx, NULL, &dummy_p, &dummy_int, NULL, 0, 0); } if (avctx->extradata_size) { if ((status = mmal_format_extradata_alloc(format_in, avctx->extradata_size))) goto fail; format_in->extradata_size = avctx->extradata_size; memcpy(format_in->extradata, avctx->extradata, format_in->extradata_size); } if ((status = mmal_port_format_commit(decoder->input[0]))) goto fail; decoder->input[0]->buffer_num = FFMAX(decoder->input[0]->buffer_num_min, 20); decoder->input[0]->buffer_size = FFMAX(decoder->input[0]->buffer_size_min, 512 * 1024); ctx->pool_in = mmal_pool_create(decoder->input[0]->buffer_num, 0); if (!ctx->pool_in) { ret = AVERROR(ENOMEM); goto fail; } if ((ret = ffmal_update_format(avctx)) < 0) goto fail; ctx->queue_decoded_frames = mmal_queue_create(); if (!ctx->queue_decoded_frames) goto fail; decoder->input[0]->userdata = (void*)avctx; decoder->output[0]->userdata = (void*)avctx; decoder->control->userdata = (void*)avctx; if ((status = mmal_port_enable(decoder->control, control_port_cb))) goto fail; if ((status = mmal_port_enable(decoder->input[0], input_callback))) goto fail; if ((status = mmal_port_enable(decoder->output[0], output_callback))) goto fail; if ((status = mmal_component_enable(decoder))) goto fail; return 0; fail: ffmmal_close_decoder(avctx); return ret < 0 ? ret : AVERROR_UNKNOWN; }
static int submit_packet(PerThreadContext *p, AVPacket *avpkt) { FrameThreadContext *fctx = p->parent; PerThreadContext *prev_thread = fctx->prev_thread; const AVCodec *codec = p->avctx->codec; if (!avpkt->size && !(codec->capabilities & CODEC_CAP_DELAY)) return 0; pthread_mutex_lock(&p->mutex); release_delayed_buffers(p); if (prev_thread) { int err; if (prev_thread->state == STATE_SETTING_UP) { pthread_mutex_lock(&prev_thread->progress_mutex); while (prev_thread->state == STATE_SETTING_UP) pthread_cond_wait(&prev_thread->progress_cond, &prev_thread->progress_mutex); pthread_mutex_unlock(&prev_thread->progress_mutex); } err = update_context_from_thread(p->avctx, prev_thread->avctx, 0); if (err) { pthread_mutex_unlock(&p->mutex); return err; } } av_packet_unref(&p->avpkt); av_packet_ref(&p->avpkt, avpkt); p->state = STATE_SETTING_UP; pthread_cond_signal(&p->input_cond); pthread_mutex_unlock(&p->mutex); /* * If the client doesn't have a thread-safe get_buffer(), * then decoding threads call back to the main thread, * and it calls back to the client here. */ FF_DISABLE_DEPRECATION_WARNINGS if (!p->avctx->thread_safe_callbacks && ( p->avctx->get_format != avcodec_default_get_format || #if FF_API_GET_BUFFER p->avctx->get_buffer || #endif p->avctx->get_buffer2 != avcodec_default_get_buffer2)) { FF_ENABLE_DEPRECATION_WARNINGS while (p->state != STATE_SETUP_FINISHED && p->state != STATE_INPUT_READY) { int call_done = 1; pthread_mutex_lock(&p->progress_mutex); while (p->state == STATE_SETTING_UP) pthread_cond_wait(&p->progress_cond, &p->progress_mutex); switch (p->state) { case STATE_GET_BUFFER: p->result = ff_get_buffer(p->avctx, p->requested_frame, p->requested_flags); break; case STATE_GET_FORMAT: p->result_format = ff_get_format(p->avctx, p->available_formats); break; default: call_done = 0; break; } if (call_done) { p->state = STATE_SETTING_UP; pthread_cond_signal(&p->progress_cond); } pthread_mutex_unlock(&p->progress_mutex); } }
int ff_qsv_decode_init(AVCodecContext *avctx, QSVContext *q, AVPacket *avpkt) { mfxVideoParam param = { { 0 } }; mfxBitstream bs = { { { 0 } } }; int ret; enum AVPixelFormat pix_fmts[3] = { AV_PIX_FMT_QSV, AV_PIX_FMT_NV12, AV_PIX_FMT_NONE }; q->iopattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY; if (!q->session) { if (avctx->hwaccel_context) { AVQSVContext *qsv = avctx->hwaccel_context; q->session = qsv->session; q->iopattern = qsv->iopattern; q->ext_buffers = qsv->ext_buffers; q->nb_ext_buffers = qsv->nb_ext_buffers; } if (!q->session) { ret = ff_qsv_init_internal_session(avctx, &q->internal_qs, q->load_plugins); if (ret < 0) return ret; q->session = q->internal_qs.session; } } if (avpkt->size) { bs.Data = avpkt->data; bs.DataLength = avpkt->size; bs.MaxLength = bs.DataLength; bs.TimeStamp = avpkt->pts; } else return AVERROR_INVALIDDATA; ret = ff_qsv_codec_id_to_mfx(avctx->codec_id); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Unsupported codec_id %08x\n", avctx->codec_id); return ret; } param.mfx.CodecId = ret; ret = MFXVideoDECODE_DecodeHeader(q->session, &bs, ¶m); if (MFX_ERR_MORE_DATA==ret) { /* this code means that header not found so we return packet size to skip a current packet */ return avpkt->size; } else if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Decode header error %d\n", ret); return ff_qsv_error(ret); } param.IOPattern = q->iopattern; param.AsyncDepth = q->async_depth; param.ExtParam = q->ext_buffers; param.NumExtParam = q->nb_ext_buffers; param.mfx.FrameInfo.BitDepthLuma = 8; param.mfx.FrameInfo.BitDepthChroma = 8; ret = MFXVideoDECODE_Init(q->session, ¶m); if (ret < 0) { if (MFX_ERR_INVALID_VIDEO_PARAM==ret) { av_log(avctx, AV_LOG_ERROR, "Error initializing the MFX video decoder, unsupported video\n"); } else { av_log(avctx, AV_LOG_ERROR, "Error initializing the MFX video decoder %d\n", ret); } return ff_qsv_error(ret); } ret = ff_get_format(avctx, pix_fmts); if (ret < 0) return ret; avctx->pix_fmt = ret; avctx->profile = param.mfx.CodecProfile; avctx->level = param.mfx.CodecLevel; avctx->coded_width = param.mfx.FrameInfo.Width; avctx->coded_height = param.mfx.FrameInfo.Height; avctx->width = param.mfx.FrameInfo.CropW - param.mfx.FrameInfo.CropX; avctx->height = param.mfx.FrameInfo.CropH - param.mfx.FrameInfo.CropY; /* maximum decoder latency should be not exceed max DPB size for h.264 and HEVC which is 16 for both cases. So weare pre-allocating fifo big enough for 17 elements: */ if (!q->async_fifo) { q->async_fifo = av_fifo_alloc((1 + 16) * (sizeof(mfxSyncPoint) + sizeof(QSVFrame*))); if (!q->async_fifo) return AVERROR(ENOMEM); } q->input_fifo = av_fifo_alloc(1024*16); if (!q->input_fifo) return AVERROR(ENOMEM); q->engine_ready = 1; return 0; }
static int CUDAAPI cuvid_handle_video_sequence(void *opaque, CUVIDEOFORMAT* format) { AVCodecContext *avctx = opaque; CuvidContext *ctx = avctx->priv_data; AVHWFramesContext *hwframe_ctx = (AVHWFramesContext*)ctx->hwframe->data; CUVIDDECODECREATEINFO cuinfo; int surface_fmt; enum AVPixelFormat pix_fmts[3] = { AV_PIX_FMT_CUDA, AV_PIX_FMT_NONE, // Will be updated below AV_PIX_FMT_NONE }; av_log(avctx, AV_LOG_TRACE, "pfnSequenceCallback, progressive_sequence=%d\n", format->progressive_sequence); ctx->internal_error = 0; switch (format->bit_depth_luma_minus8) { case 0: // 8-bit pix_fmts[1] = AV_PIX_FMT_NV12; break; case 2: // 10-bit pix_fmts[1] = AV_PIX_FMT_P010; break; case 4: // 12-bit pix_fmts[1] = AV_PIX_FMT_P016; break; default: av_log(avctx, AV_LOG_ERROR, "unsupported bit depth: %d\n", format->bit_depth_luma_minus8 + 8); ctx->internal_error = AVERROR(EINVAL); return 0; } surface_fmt = ff_get_format(avctx, pix_fmts); if (surface_fmt < 0) { av_log(avctx, AV_LOG_ERROR, "ff_get_format failed: %d\n", surface_fmt); ctx->internal_error = AVERROR(EINVAL); return 0; } av_log(avctx, AV_LOG_VERBOSE, "Formats: Original: %s | HW: %s | SW: %s\n", av_get_pix_fmt_name(avctx->pix_fmt), av_get_pix_fmt_name(surface_fmt), av_get_pix_fmt_name(avctx->sw_pix_fmt)); avctx->pix_fmt = surface_fmt; avctx->width = format->display_area.right; avctx->height = format->display_area.bottom; ff_set_sar(avctx, av_div_q( (AVRational){ format->display_aspect_ratio.x, format->display_aspect_ratio.y }, (AVRational){ avctx->width, avctx->height })); if (!format->progressive_sequence && ctx->deint_mode == cudaVideoDeinterlaceMode_Weave) avctx->flags |= AV_CODEC_FLAG_INTERLACED_DCT; else avctx->flags &= ~AV_CODEC_FLAG_INTERLACED_DCT; if (format->video_signal_description.video_full_range_flag) avctx->color_range = AVCOL_RANGE_JPEG; else avctx->color_range = AVCOL_RANGE_MPEG; avctx->color_primaries = format->video_signal_description.color_primaries; avctx->color_trc = format->video_signal_description.transfer_characteristics; avctx->colorspace = format->video_signal_description.matrix_coefficients; if (format->bitrate) avctx->bit_rate = format->bitrate; if (format->frame_rate.numerator && format->frame_rate.denominator) { avctx->framerate.num = format->frame_rate.numerator; avctx->framerate.den = format->frame_rate.denominator; } if (ctx->cudecoder && avctx->coded_width == format->coded_width && avctx->coded_height == format->coded_height && ctx->chroma_format == format->chroma_format && ctx->codec_type == format->codec) return 1; if (ctx->cudecoder) { av_log(avctx, AV_LOG_TRACE, "Re-initializing decoder\n"); ctx->internal_error = CHECK_CU(ctx->cvdl->cuvidDestroyDecoder(ctx->cudecoder)); if (ctx->internal_error < 0) return 0; ctx->cudecoder = NULL; } if (hwframe_ctx->pool && ( hwframe_ctx->width < avctx->width || hwframe_ctx->height < avctx->height || hwframe_ctx->format != AV_PIX_FMT_CUDA || hwframe_ctx->sw_format != avctx->sw_pix_fmt)) { av_log(avctx, AV_LOG_ERROR, "AVHWFramesContext is already initialized with incompatible parameters\n"); ctx->internal_error = AVERROR(EINVAL); return 0; } if (format->chroma_format != cudaVideoChromaFormat_420) { av_log(avctx, AV_LOG_ERROR, "Chroma formats other than 420 are not supported\n"); ctx->internal_error = AVERROR(EINVAL); return 0; } avctx->coded_width = format->coded_width; avctx->coded_height = format->coded_height; ctx->chroma_format = format->chroma_format; memset(&cuinfo, 0, sizeof(cuinfo)); cuinfo.CodecType = ctx->codec_type = format->codec; cuinfo.ChromaFormat = format->chroma_format; switch (avctx->sw_pix_fmt) { case AV_PIX_FMT_NV12: cuinfo.OutputFormat = cudaVideoSurfaceFormat_NV12; break; case AV_PIX_FMT_P010: case AV_PIX_FMT_P016: cuinfo.OutputFormat = cudaVideoSurfaceFormat_P016; break; default: av_log(avctx, AV_LOG_ERROR, "Output formats other than NV12, P010 or P016 are not supported\n"); ctx->internal_error = AVERROR(EINVAL); return 0; } cuinfo.ulWidth = avctx->coded_width; cuinfo.ulHeight = avctx->coded_height; cuinfo.ulTargetWidth = cuinfo.ulWidth; cuinfo.ulTargetHeight = cuinfo.ulHeight; cuinfo.target_rect.left = 0; cuinfo.target_rect.top = 0; cuinfo.target_rect.right = cuinfo.ulWidth; cuinfo.target_rect.bottom = cuinfo.ulHeight; cuinfo.ulNumDecodeSurfaces = ctx->nb_surfaces; cuinfo.ulNumOutputSurfaces = 1; cuinfo.ulCreationFlags = cudaVideoCreate_PreferCUVID; cuinfo.bitDepthMinus8 = format->bit_depth_luma_minus8; if (format->progressive_sequence) { ctx->deint_mode = cuinfo.DeinterlaceMode = cudaVideoDeinterlaceMode_Weave; } else { cuinfo.DeinterlaceMode = ctx->deint_mode; } if (ctx->deint_mode != cudaVideoDeinterlaceMode_Weave) avctx->framerate = av_mul_q(avctx->framerate, (AVRational){2, 1}); ctx->internal_error = CHECK_CU(ctx->cvdl->cuvidCreateDecoder(&ctx->cudecoder, &cuinfo)); if (ctx->internal_error < 0) return 0; if (!hwframe_ctx->pool) { hwframe_ctx->format = AV_PIX_FMT_CUDA; hwframe_ctx->sw_format = avctx->sw_pix_fmt; hwframe_ctx->width = avctx->width; hwframe_ctx->height = avctx->height; if ((ctx->internal_error = av_hwframe_ctx_init(ctx->hwframe)) < 0) { av_log(avctx, AV_LOG_ERROR, "av_hwframe_ctx_init failed\n"); return 0; } } return 1; }
static int CUDAAPI cuvid_handle_video_sequence(void *opaque, CUVIDEOFORMAT* format) { AVCodecContext *avctx = opaque; CuvidContext *ctx = avctx->priv_data; AVHWFramesContext *hwframe_ctx = (AVHWFramesContext*)ctx->hwframe->data; CUVIDDECODECAPS *caps = NULL; CUVIDDECODECREATEINFO cuinfo; int surface_fmt; int old_width = avctx->width; int old_height = avctx->height; enum AVPixelFormat pix_fmts[3] = { AV_PIX_FMT_CUDA, AV_PIX_FMT_NONE, // Will be updated below AV_PIX_FMT_NONE }; av_log(avctx, AV_LOG_TRACE, "pfnSequenceCallback, progressive_sequence=%d\n", format->progressive_sequence); memset(&cuinfo, 0, sizeof(cuinfo)); ctx->internal_error = 0; avctx->coded_width = cuinfo.ulWidth = format->coded_width; avctx->coded_height = cuinfo.ulHeight = format->coded_height; // apply cropping cuinfo.display_area.left = format->display_area.left + ctx->crop.left; cuinfo.display_area.top = format->display_area.top + ctx->crop.top; cuinfo.display_area.right = format->display_area.right - ctx->crop.right; cuinfo.display_area.bottom = format->display_area.bottom - ctx->crop.bottom; // width and height need to be set before calling ff_get_format if (ctx->resize_expr) { avctx->width = ctx->resize.width; avctx->height = ctx->resize.height; } else { avctx->width = cuinfo.display_area.right - cuinfo.display_area.left; avctx->height = cuinfo.display_area.bottom - cuinfo.display_area.top; } // target width/height need to be multiples of two cuinfo.ulTargetWidth = avctx->width = (avctx->width + 1) & ~1; cuinfo.ulTargetHeight = avctx->height = (avctx->height + 1) & ~1; // aspect ratio conversion, 1:1, depends on scaled resolution cuinfo.target_rect.left = 0; cuinfo.target_rect.top = 0; cuinfo.target_rect.right = cuinfo.ulTargetWidth; cuinfo.target_rect.bottom = cuinfo.ulTargetHeight; switch (format->bit_depth_luma_minus8) { case 0: // 8-bit pix_fmts[1] = AV_PIX_FMT_NV12; caps = &ctx->caps8; break; case 2: // 10-bit pix_fmts[1] = AV_PIX_FMT_P010; caps = &ctx->caps10; break; case 4: // 12-bit pix_fmts[1] = AV_PIX_FMT_P016; caps = &ctx->caps12; break; default: break; } if (!caps || !caps->bIsSupported) { av_log(avctx, AV_LOG_ERROR, "unsupported bit depth: %d\n", format->bit_depth_luma_minus8 + 8); ctx->internal_error = AVERROR(EINVAL); return 0; } surface_fmt = ff_get_format(avctx, pix_fmts); if (surface_fmt < 0) { av_log(avctx, AV_LOG_ERROR, "ff_get_format failed: %d\n", surface_fmt); ctx->internal_error = AVERROR(EINVAL); return 0; } av_log(avctx, AV_LOG_VERBOSE, "Formats: Original: %s | HW: %s | SW: %s\n", av_get_pix_fmt_name(avctx->pix_fmt), av_get_pix_fmt_name(surface_fmt), av_get_pix_fmt_name(avctx->sw_pix_fmt)); avctx->pix_fmt = surface_fmt; // Update our hwframe ctx, as the get_format callback might have refreshed it! if (avctx->hw_frames_ctx) { av_buffer_unref(&ctx->hwframe); ctx->hwframe = av_buffer_ref(avctx->hw_frames_ctx); if (!ctx->hwframe) { ctx->internal_error = AVERROR(ENOMEM); return 0; } hwframe_ctx = (AVHWFramesContext*)ctx->hwframe->data; } ff_set_sar(avctx, av_div_q( (AVRational){ format->display_aspect_ratio.x, format->display_aspect_ratio.y }, (AVRational){ avctx->width, avctx->height })); ctx->deint_mode_current = format->progressive_sequence ? cudaVideoDeinterlaceMode_Weave : ctx->deint_mode; if (!format->progressive_sequence && ctx->deint_mode_current == cudaVideoDeinterlaceMode_Weave) avctx->flags |= AV_CODEC_FLAG_INTERLACED_DCT; else avctx->flags &= ~AV_CODEC_FLAG_INTERLACED_DCT; if (format->video_signal_description.video_full_range_flag) avctx->color_range = AVCOL_RANGE_JPEG; else avctx->color_range = AVCOL_RANGE_MPEG; avctx->color_primaries = format->video_signal_description.color_primaries; avctx->color_trc = format->video_signal_description.transfer_characteristics; avctx->colorspace = format->video_signal_description.matrix_coefficients; if (format->bitrate) avctx->bit_rate = format->bitrate; if (format->frame_rate.numerator && format->frame_rate.denominator) { avctx->framerate.num = format->frame_rate.numerator; avctx->framerate.den = format->frame_rate.denominator; } if (ctx->cudecoder && avctx->coded_width == format->coded_width && avctx->coded_height == format->coded_height && avctx->width == old_width && avctx->height == old_height && ctx->chroma_format == format->chroma_format && ctx->codec_type == format->codec) return 1; if (ctx->cudecoder) { av_log(avctx, AV_LOG_TRACE, "Re-initializing decoder\n"); ctx->internal_error = CHECK_CU(ctx->cvdl->cuvidDestroyDecoder(ctx->cudecoder)); if (ctx->internal_error < 0) return 0; ctx->cudecoder = NULL; } if (hwframe_ctx->pool && ( hwframe_ctx->width < avctx->width || hwframe_ctx->height < avctx->height || hwframe_ctx->format != AV_PIX_FMT_CUDA || hwframe_ctx->sw_format != avctx->sw_pix_fmt)) { av_log(avctx, AV_LOG_ERROR, "AVHWFramesContext is already initialized with incompatible parameters\n"); av_log(avctx, AV_LOG_DEBUG, "width: %d <-> %d\n", hwframe_ctx->width, avctx->width); av_log(avctx, AV_LOG_DEBUG, "height: %d <-> %d\n", hwframe_ctx->height, avctx->height); av_log(avctx, AV_LOG_DEBUG, "format: %s <-> cuda\n", av_get_pix_fmt_name(hwframe_ctx->format)); av_log(avctx, AV_LOG_DEBUG, "sw_format: %s <-> %s\n", av_get_pix_fmt_name(hwframe_ctx->sw_format), av_get_pix_fmt_name(avctx->sw_pix_fmt)); ctx->internal_error = AVERROR(EINVAL); return 0; } if (format->chroma_format != cudaVideoChromaFormat_420) { av_log(avctx, AV_LOG_ERROR, "Chroma formats other than 420 are not supported\n"); ctx->internal_error = AVERROR(EINVAL); return 0; } ctx->chroma_format = format->chroma_format; cuinfo.CodecType = ctx->codec_type = format->codec; cuinfo.ChromaFormat = format->chroma_format; switch (avctx->sw_pix_fmt) { case AV_PIX_FMT_NV12: cuinfo.OutputFormat = cudaVideoSurfaceFormat_NV12; break; case AV_PIX_FMT_P010: case AV_PIX_FMT_P016: cuinfo.OutputFormat = cudaVideoSurfaceFormat_P016; break; default: av_log(avctx, AV_LOG_ERROR, "Output formats other than NV12, P010 or P016 are not supported\n"); ctx->internal_error = AVERROR(EINVAL); return 0; } cuinfo.ulNumDecodeSurfaces = ctx->nb_surfaces; cuinfo.ulNumOutputSurfaces = 1; cuinfo.ulCreationFlags = cudaVideoCreate_PreferCUVID; cuinfo.bitDepthMinus8 = format->bit_depth_luma_minus8; cuinfo.DeinterlaceMode = ctx->deint_mode_current; if (ctx->deint_mode_current != cudaVideoDeinterlaceMode_Weave && !ctx->drop_second_field) avctx->framerate = av_mul_q(avctx->framerate, (AVRational){2, 1}); ctx->internal_error = CHECK_CU(ctx->cvdl->cuvidCreateDecoder(&ctx->cudecoder, &cuinfo)); if (ctx->internal_error < 0) return 0; if (!hwframe_ctx->pool) { hwframe_ctx->format = AV_PIX_FMT_CUDA; hwframe_ctx->sw_format = avctx->sw_pix_fmt; hwframe_ctx->width = avctx->width; hwframe_ctx->height = avctx->height; if ((ctx->internal_error = av_hwframe_ctx_init(ctx->hwframe)) < 0) { av_log(avctx, AV_LOG_ERROR, "av_hwframe_ctx_init failed\n"); return 0; } } return 1; }