static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context, AVFrame *p_ff_pic ) { decoder_t *p_dec = (decoder_t *)p_context->opaque; decoder_sys_t *p_sys = p_dec->p_sys; /* */ p_ff_pic->opaque = NULL; #if ! LIBAVCODEC_VERSION_CHECK(54, 34, 0, 79, 101) p_ff_pic->pkt_pts = p_context->pkt ? p_context->pkt->pts : AV_NOPTS_VALUE; #endif #if LIBAVCODEC_VERSION_MAJOR < 54 p_ff_pic->age = 256*256*256*64; #endif if( p_sys->p_va ) return ffmpeg_va_GetFrameBuf(p_context, p_ff_pic); if( !p_sys->b_direct_rendering ) return avcodec_default_get_buffer( p_context, p_ff_pic ); wait_mt( p_sys ); /* Some codecs set pix_fmt only after the 1st frame has been decoded, * so we need to check for direct rendering again. */ picture_t *p_pic = ffmpeg_dr_GetFrameBuf(p_context); if (!p_pic) { if( p_sys->i_direct_rendering_used != 0 ) { msg_Warn( p_dec, "disabling direct rendering" ); p_sys->i_direct_rendering_used = 0; } post_mt( p_sys ); return avcodec_default_get_buffer( p_context, p_ff_pic ); } if( p_sys->i_direct_rendering_used != 1 ) { msg_Dbg( p_dec, "using direct rendering" ); p_sys->i_direct_rendering_used = 1; } p_context->draw_horiz_band = NULL; post_mt( p_sys ); p_ff_pic->opaque = (void*)p_pic; p_ff_pic->type = FF_BUFFER_TYPE_USER; p_ff_pic->data[0] = p_pic->p[0].p_pixels; p_ff_pic->data[1] = p_pic->p[1].p_pixels; p_ff_pic->data[2] = p_pic->p[2].p_pixels; p_ff_pic->data[3] = NULL; /* alpha channel but I'm not sure */ p_ff_pic->linesize[0] = p_pic->p[0].i_pitch; p_ff_pic->linesize[1] = p_pic->p[1].i_pitch; p_ff_pic->linesize[2] = p_pic->p[2].i_pitch; p_ff_pic->linesize[3] = 0; return 0; }
int ac_get_buffer(struct AVCodecContext *c, AVFrame *pic) { int ret = avcodec_default_get_buffer(c, pic); uint64_t *pts = av_malloc(sizeof(uint64_t)); *pts = AV_NOPTS_VALUE; pic->opaque = pts; return ret; }
int our_get_buffer(struct AVCodecContext *c, AVFrame *pic, int flags) { int ret = avcodec_default_get_buffer(c, pic); uint64_t *pts = av_malloc(sizeof(uint64_t)); *pts = global_video_pkt_pts; pic->opaque = pts; return ret; }
int get_buffer_with_pts(struct AVCodecContext *ctx, AVFrame *frame) { int ret = avcodec_default_get_buffer(ctx, frame); uint64_t *pts = (uint64_t*)av_malloc(sizeof(uint64_t)); *pts = AV_NOPTS_VALUE; frame->opaque = pts; return ret; }
int frame_storage_alloc(AVCodecContext *c, AVFrame *frame) { /* round width and height to integer macroblock multiples */ const int width = (2 * (c->width + ((1 << mb_size_log) - 1)) >> mb_size_log) << mb_size_log; const int height = (2 * (c->height + ((1 << mb_size_log) - 1)) >> mb_size_log) << mb_size_log; frame->opaque = av_malloc(avpicture_get_size(c->pix_fmt, width, height)); return avcodec_default_get_buffer(c, frame); }
/* These are called whenever we allocate a frame * buffer. We use this to store the global_pts in * a frame at the time it is allocated. */ int our_get_buffer(struct AVCodecContext *c, AVFrame *pic) { int ret = avcodec_default_get_buffer(c, pic); uint64_t *pts = av_malloc(sizeof(uint64_t)); // We set the wrong value here: global_video_pkt_pts *pts = global_video_pkt_pts; pic->opaque = pts; return ret; }
int our_get_buffer(struct AVCodecContext *c, AVFrame *pic) { int ret = avcodec_default_get_buffer(c, pic); uint64_t *pts = (uint64_t*)av_mallocz(sizeof(uint64_t)); *pts = global_video_pkt_pts; pic->opaque = pts; //fprintf(stderr, "2: AVFrame.pkt_pts = %lld\n", pic->opaque); return ret; }
int our_get_buffer(struct AVCodecContext *c, AVFrame *pic) { int ret = avcodec_default_get_buffer(c, pic); uint64_t *pts = new uint64_t; *pts = global_video_pkt_pts; pic->opaque = pts; return ret; }
int hack_get_buffer(struct AVCodecContext *c, AVFrame *pic) { PlayerCtx *ctx = (PlayerCtx*) c->opaque; int ret = avcodec_default_get_buffer(c, pic); uint64_t *pts = av_malloc(sizeof(uint64_t)); *pts = ctx->v_pkt_pts; pic->opaque = pts; return ret; }
static int vd_get_buffer(struct AVCodecContext *c, AVFrame *pic) { int ret = avcodec_default_get_buffer(c, pic); media_buf_t *mb = malloc(sizeof(media_buf_t)); memcpy(mb, c->opaque, sizeof(media_buf_t)); pic->opaque = mb; return ret; }
static int flow_get_buffer(struct AVCodecContext *c, AVFrame *pic) { int ret = avcodec_default_get_buffer(c, pic); uint64_t *pts = (uint64_t*)av_malloc(sizeof(uint64_t)); *pts = global_video_pkt_pts; pic->opaque = pts; //printf("Called malloc buffer\n"); return ret; }
int FFMpegDecoder::my_get_buffer(struct AVCodecContext *c, AVFrame *pic) { int ret = avcodec_default_get_buffer(c, pic); if (ret) errinfo("avcodec_default_get_buffer failed!\n"); uint64_t *pts = (uint64_t*)av_malloc(sizeof(uint64_t)); *pts = my_video_pkt_pts; pic->opaque = pts; return ret; }
FF_DISABLE_DEPRECATION_WARNINGS static int I_AVGetBufferProc(struct AVCodecContext *c, AVFrame *pic) { int ret = avcodec_default_get_buffer(c, pic); uint64_t *pts = av_malloc(sizeof(uint64_t)); *pts = globalPts; pic->opaque = pts; return ret; }
int FFmpegDecoderVideo::getBuffer(AVCodecContext * const context, AVFrame * const picture) { const FFmpegDecoderVideo * const this_ = reinterpret_cast<const FFmpegDecoderVideo*>(context->opaque); const int result = avcodec_default_get_buffer(context, picture); int64_t * p_pts = reinterpret_cast<int64_t*>( av_malloc(sizeof(int64_t)) ); *p_pts = this_->m_packet_pts; picture->opaque = p_pts; return result; }
static int GetBuffer(struct AVCodecContext *Context, AVFrame *Frame) { if (!Context->codec) return -1; if (!(Context->codec->capabilities & CODEC_CAP_DR1)) return avcodec_default_get_buffer(Context, Frame); VideoDecoder *parent = static_cast<VideoDecoder*>(Context->opaque); if (parent) return parent->GetAVBuffer(Context, Frame); LOG(VB_GENERAL, LOG_ERR, "Invalid context"); return -1; }
/* static */ int FFmpegH264Decoder<LIBAV_VER>::AllocateBufferCb(AVCodecContext* aCodecContext, AVFrame* aFrame) { MOZ_ASSERT(aCodecContext->codec_type == AVMEDIA_TYPE_VIDEO); FFmpegH264Decoder* self = static_cast<FFmpegH264Decoder*>(aCodecContext->opaque); switch (aCodecContext->pix_fmt) { case PIX_FMT_YUV420P: return self->AllocateYUV420PVideoBuffer(aCodecContext, aFrame); default: return avcodec_default_get_buffer(aCodecContext, aFrame); } }
static int get_buffer(AVCodecContext *vcodec_ctx, AVFrame *vcodec_picture) { VideoDecoder *vdec = (VideoDecoder *)vcodec_ctx->opaque; struct videodecoder_avcodec *vdm = (struct videodecoder_avcodec *)vdec->opaque; int width, height; Picture_buffer *buf; /* alignment */ width = (vcodec_ctx->width + 15) & ~15; height = (vcodec_ctx->height + 15) & ~15; if (vcodec_ctx->pix_fmt != PIX_FMT_YUV420P || width != vcodec_ctx->width || height != vcodec_ctx->height) { debug_message_fnc("avcodec: unsupported frame format, DR1 disabled.\n"); vdm->vcodec_ctx->get_buffer = avcodec_default_get_buffer; vdm->vcodec_ctx->reget_buffer = avcodec_default_reget_buffer; vdm->vcodec_ctx->release_buffer = avcodec_default_release_buffer; return avcodec_default_get_buffer(vcodec_ctx, vcodec_picture); } buf = &vdm->picture_buffer[vdm->picture_buffer_count]; if (buf->base == NULL) { int datasize = image_bpl(vdm->p) * image_height(vdm->p); int size = sizeof(struct pic_buf) + datasize; struct pic_buf *pb; if ((buf->base = memory_create()) == NULL) { err_message_fnc("No enough memory for Memory object buf->base.\n"); return -1; } if ((pb = memory_alloc(buf->base, size)) == NULL) { err_message_fnc("Cannot allocate %d bytes. No enough memory for pic_buf.\n", size); return -1; } pb->idx = vdm->picture_buffer_count; pb->mem = buf->base; memset(pb->data, 128, datasize); buf->pb = pb; buf->linesize[0] = image_width(vdm->p); buf->linesize[1] = image_width(vdm->p) >> 1; buf->linesize[2] = image_width(vdm->p) >> 1; }
/* called when ffmpeg wants us to allocate a buffer to write the decoded frame * into. We try to give it memory from our pool */ static int gst_ffmpegauddec_get_buffer (AVCodecContext * context, AVFrame * frame) { GstFFMpegAudDec *ffmpegdec; GstAudioInfo *info; BufferInfo *buffer_info; ffmpegdec = (GstFFMpegAudDec *) context->opaque; if (G_UNLIKELY (!gst_ffmpegauddec_negotiate (ffmpegdec, FALSE))) goto negotiate_failed; /* Always use the default allocator for planar audio formats because * we will have to copy and deinterleave later anyway */ if (av_sample_fmt_is_planar (ffmpegdec->context->sample_fmt)) goto fallback; info = gst_audio_decoder_get_audio_info (GST_AUDIO_DECODER (ffmpegdec)); buffer_info = g_slice_new (BufferInfo); buffer_info->buffer = gst_audio_decoder_allocate_output_buffer (GST_AUDIO_DECODER (ffmpegdec), frame->nb_samples * info->bpf); gst_buffer_map (buffer_info->buffer, &buffer_info->map, GST_MAP_WRITE); frame->opaque = buffer_info; frame->data[0] = buffer_info->map.data; frame->extended_data = frame->data; frame->linesize[0] = buffer_info->map.size; frame->type = FF_BUFFER_TYPE_USER; return 0; /* fallbacks */ negotiate_failed: { GST_DEBUG_OBJECT (ffmpegdec, "negotiate failed"); goto fallback; } fallback: { return avcodec_default_get_buffer (context, frame); } }
static int alloc_picture(MpegEncContext *s, Picture *pic, int shared) { const int big_mb_num= s->mb_stride*(s->mb_height+1) + 1; //the +1 is needed so memset(,,stride*height) doesnt sig11 const int mb_array_size= s->mb_stride*s->mb_height; const int b8_array_size= s->b8_stride*s->mb_height*2; const int b4_array_size= s->b4_stride*s->mb_height*4; int i; int r; r= avcodec_default_get_buffer(s->avctx, (AVFrame*)pic); if(r<0 || !pic->data[0]) return -1; if(s->linesize && (s->linesize != pic->linesize[0] || s->uvlinesize != pic->linesize[1])) return -1; if(pic->linesize[1] != pic->linesize[2]) return -1; s->linesize = pic->linesize[0]; s->uvlinesize= pic->linesize[1]; if(pic->qscale_table==NULL) { CHECKED_ALLOCZ(pic->qscale_table , mb_array_size * sizeof(uint8_t)); CHECKED_ALLOCZ(pic->mb_type_base , big_mb_num * sizeof(uint32_t)); pic->mb_type= pic->mb_type_base + s->mb_stride+1; for(i=0; i<2; i++) { CHECKED_ALLOCZ(pic->motion_val_base[i], 2 * (b4_array_size+2) * sizeof(int16_t)); pic->motion_val[i]= pic->motion_val_base[i]+2; CHECKED_ALLOCZ(pic->ref_index[i] , b8_array_size * sizeof(uint8_t)); } } return 0; fail: //for the CHECKED_ALLOCZ macro return -1; }
/** @internal @This is called by avcodec when allocating a new audio buffer * Used with audio decoders. * @param context current avcodec context * @param frame avframe handler entering avcodec black magic box */ static int upipe_avcdec_get_buffer_audio(struct AVCodecContext *context, AVFrame *frame) { struct upipe *upipe = context->opaque; struct upipe_avcdec *upipe_avcdec = upipe_avcdec_from_upipe(upipe); struct ubuf *ubuf_samples; uint8_t *buf; int size; frame->opaque = uref_dup(upipe_avcdec->uref); /* direct rendering - allocate ubuf for audio */ if (upipe_avcdec->context->codec->capabilities & CODEC_CAP_DR1) { ubuf_samples = ubuf_block_alloc(upipe_avcdec->ubuf_mgr, av_samples_get_buffer_size(NULL, context->channels, frame->nb_samples, context->sample_fmt, 1)); if (likely(ubuf_samples)) { ubuf_block_write(ubuf_samples, 0, &size, &buf); uref_attach_ubuf(frame->opaque, ubuf_samples); av_samples_fill_arrays(frame->data, frame->linesize, buf, context->channels, frame->nb_samples, context->sample_fmt, 1); frame->extended_data = frame->data; frame->type = FF_BUFFER_TYPE_USER; return 1; /* success */ } else { upipe_dbg_va(upipe, "ubuf allocation failed, fallback"); } } /* default : DR failed or not available */ return avcodec_default_get_buffer(context, frame); }
bool AVIDump::CreateFile() { AVCodec* codec = nullptr; s_format_context = avformat_alloc_context(); std::stringstream s_file_index_str; s_file_index_str << s_file_index; snprintf(s_format_context->filename, sizeof(s_format_context->filename), "%s", (File::GetUserPath(D_DUMPFRAMES_IDX) + "framedump" + s_file_index_str.str() + ".avi") .c_str()); File::CreateFullPath(s_format_context->filename); // Ask to delete file if (File::Exists(s_format_context->filename)) { if (SConfig::GetInstance().m_DumpFramesSilent || AskYesNoT("Delete the existing file '%s'?", s_format_context->filename)) { File::Delete(s_format_context->filename); } else { // Stop and cancel dumping the video return false; } } if (!(s_format_context->oformat = av_guess_format("avi", nullptr, nullptr)) || !(s_stream = avformat_new_stream(s_format_context, codec))) { return false; } s_stream->codec->codec_id = g_Config.bUseFFV1 ? AV_CODEC_ID_FFV1 : s_format_context->oformat->video_codec; if (!g_Config.bUseFFV1) s_stream->codec->codec_tag = MKTAG('X', 'V', 'I', 'D'); // Force XVID FourCC for better compatibility s_stream->codec->codec_type = AVMEDIA_TYPE_VIDEO; s_stream->codec->bit_rate = 400000; s_stream->codec->width = s_width; s_stream->codec->height = s_height; s_stream->codec->time_base.num = 1; s_stream->codec->time_base.den = VideoInterface::GetTargetRefreshRate(); s_stream->codec->gop_size = 12; s_stream->codec->pix_fmt = g_Config.bUseFFV1 ? AV_PIX_FMT_BGRA : AV_PIX_FMT_YUV420P; if (!(codec = avcodec_find_encoder(s_stream->codec->codec_id)) || (avcodec_open2(s_stream->codec, codec, nullptr) < 0)) { return false; } s_src_frame = av_frame_alloc(); s_scaled_frame = av_frame_alloc(); s_scaled_frame->format = s_stream->codec->pix_fmt; s_scaled_frame->width = s_width; s_scaled_frame->height = s_height; #if LIBAVCODEC_VERSION_MAJOR >= 55 if (av_frame_get_buffer(s_scaled_frame, 1)) return false; #else if (avcodec_default_get_buffer(s_stream->codec, s_scaled_frame)) return false; #endif NOTICE_LOG(VIDEO, "Opening file %s for dumping", s_format_context->filename); if (avio_open(&s_format_context->pb, s_format_context->filename, AVIO_FLAG_WRITE) < 0 || avformat_write_header(s_format_context, nullptr)) { WARN_LOG(VIDEO, "Could not open %s", s_format_context->filename); return false; } OSD::AddMessage(StringFromFormat("Dumping Frames to \"%s\" (%dx%d)", s_format_context->filename, s_width, s_height)); return true; }
bool AVIDump::CreateVideoFile() { const std::string& format = g_Config.sDumpFormat; const std::string dump_path = GetDumpPath(format); if (dump_path.empty()) return false; File::CreateFullPath(dump_path); AVOutputFormat* output_format = av_guess_format(format.c_str(), dump_path.c_str(), nullptr); if (!output_format) { ERROR_LOG(VIDEO, "Invalid format %s", format.c_str()); return false; } if (avformat_alloc_output_context2(&s_format_context, output_format, nullptr, dump_path.c_str()) < 0) { ERROR_LOG(VIDEO, "Could not allocate output context"); return false; } const std::string& codec_name = g_Config.bUseFFV1 ? "ffv1" : g_Config.sDumpCodec; AVCodecID codec_id = output_format->video_codec; if (!codec_name.empty()) { const AVCodecDescriptor* codec_desc = avcodec_descriptor_get_by_name(codec_name.c_str()); if (codec_desc) codec_id = codec_desc->id; else WARN_LOG(VIDEO, "Invalid codec %s", codec_name.c_str()); } const AVCodec* codec = nullptr; if (!g_Config.sDumpEncoder.empty()) { codec = avcodec_find_encoder_by_name(g_Config.sDumpEncoder.c_str()); if (!codec) WARN_LOG(VIDEO, "Invalid encoder %s", g_Config.sDumpEncoder.c_str()); } if (!codec) codec = avcodec_find_encoder(codec_id); s_codec_context = avcodec_alloc_context3(codec); if (!codec || !s_codec_context) { ERROR_LOG(VIDEO, "Could not find encoder or allocate codec context"); return false; } // Force XVID FourCC for better compatibility if (codec->id == AV_CODEC_ID_MPEG4) s_codec_context->codec_tag = MKTAG('X', 'V', 'I', 'D'); s_codec_context->codec_type = AVMEDIA_TYPE_VIDEO; s_codec_context->bit_rate = g_Config.iBitrateKbps * 1000; s_codec_context->width = s_width; s_codec_context->height = s_height; s_codec_context->time_base.num = 1; s_codec_context->time_base.den = VideoInterface::GetTargetRefreshRate(); s_codec_context->gop_size = 12; s_codec_context->pix_fmt = g_Config.bUseFFV1 ? AV_PIX_FMT_BGRA : AV_PIX_FMT_YUV420P; if (output_format->flags & AVFMT_GLOBALHEADER) s_codec_context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; if (avcodec_open2(s_codec_context, codec, nullptr) < 0) { ERROR_LOG(VIDEO, "Could not open codec"); return false; } s_src_frame = av_frame_alloc(); s_scaled_frame = av_frame_alloc(); s_scaled_frame->format = s_codec_context->pix_fmt; s_scaled_frame->width = s_width; s_scaled_frame->height = s_height; #if LIBAVCODEC_VERSION_MAJOR >= 55 if (av_frame_get_buffer(s_scaled_frame, 1)) return false; #else if (avcodec_default_get_buffer(s_codec_context, s_scaled_frame)) return false; #endif s_stream = avformat_new_stream(s_format_context, codec); if (!s_stream || !AVStreamCopyContext(s_stream, s_codec_context)) { ERROR_LOG(VIDEO, "Could not create stream"); return false; } NOTICE_LOG(VIDEO, "Opening file %s for dumping", s_format_context->filename); if (avio_open(&s_format_context->pb, s_format_context->filename, AVIO_FLAG_WRITE) < 0 || avformat_write_header(s_format_context, nullptr)) { ERROR_LOG(VIDEO, "Could not open %s", s_format_context->filename); return false; } OSD::AddMessage(StringFromFormat("Dumping Frames to \"%s\" (%dx%d)", s_format_context->filename, s_width, s_height)); return true; }
static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context, AVFrame *p_ff_pic ) { decoder_t *p_dec = (decoder_t *)p_context->opaque; decoder_sys_t *p_sys = p_dec->p_sys; picture_t *p_pic; /* Set picture PTS */ ffmpeg_SetFrameBufferPts( p_dec, p_ff_pic ); /* */ p_ff_pic->opaque = NULL; if( p_sys->p_va ) { #ifdef HAVE_AVCODEC_VAAPI /* hwaccel_context is not present in old fffmpeg version */ if( VaSetup( p_sys->p_va, &p_sys->p_context->hwaccel_context, &p_dec->fmt_out.video.i_chroma, p_sys->p_context->width, p_sys->p_context->height ) ) { msg_Err( p_dec, "VaSetup failed" ); return -1; } #else assert(0); #endif /* */ p_ff_pic->type = FF_BUFFER_TYPE_USER; /* FIXME what is that, should give good value */ p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg if( VaGrabSurface( p_sys->p_va, p_ff_pic ) ) { msg_Err( p_dec, "VaGrabSurface failed" ); return -1; } return 0; } else if( !p_sys->b_direct_rendering ) { /* Not much to do in indirect rendering mode */ return avcodec_default_get_buffer( p_context, p_ff_pic ); } /* Some codecs set pix_fmt only after the 1st frame has been decoded, * so we need to check for direct rendering again. */ int i_width = p_sys->p_context->width; int i_height = p_sys->p_context->height; avcodec_align_dimensions( p_sys->p_context, &i_width, &i_height ); if( GetVlcChroma( &p_dec->fmt_out.video, p_context->pix_fmt ) != VLC_SUCCESS || p_sys->p_context->width % 16 || p_sys->p_context->height % 16 || /* We only pad picture up to 16 */ PAD(p_sys->p_context->width,16) < i_width || PAD(p_sys->p_context->height,16) < i_height || p_context->pix_fmt == PIX_FMT_PAL8 ) return avcodec_default_get_buffer( p_context, p_ff_pic ); p_dec->fmt_out.i_codec = p_dec->fmt_out.video.i_chroma; /* Get a new picture */ p_pic = ffmpeg_NewPictBuf( p_dec, p_sys->p_context ); if( !p_pic ) return avcodec_default_get_buffer( p_context, p_ff_pic ); p_sys->p_context->draw_horiz_band = NULL; p_ff_pic->opaque = (void*)p_pic; p_ff_pic->type = FF_BUFFER_TYPE_USER; p_ff_pic->data[0] = p_pic->p[0].p_pixels; p_ff_pic->data[1] = p_pic->p[1].p_pixels; p_ff_pic->data[2] = p_pic->p[2].p_pixels; p_ff_pic->data[3] = NULL; /* alpha channel but I'm not sure */ p_ff_pic->linesize[0] = p_pic->p[0].i_pitch; p_ff_pic->linesize[1] = p_pic->p[1].i_pitch; p_ff_pic->linesize[2] = p_pic->p[2].i_pitch; p_ff_pic->linesize[3] = 0; decoder_LinkPicture( p_dec, p_pic ); /* FIXME what is that, should give good value */ p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg return 0; }
/** @internal @This is called by avcodec when allocating a new frame * @param context current avcodec context * @param frame avframe handler entering avcodec black magic box */ static int upipe_avcdec_get_buffer(struct AVCodecContext *context, AVFrame *frame) { struct upipe *upipe = context->opaque; struct upipe_avcdec *upipe_avcdec = upipe_avcdec_from_upipe(upipe); struct ubuf *ubuf_pic; int width_aligned, height_aligned, i; const struct upipe_av_plane *planes = NULL; size_t stride = 0; frame->opaque = uref_dup(upipe_avcdec->uref); uint64_t framenum = 0; uref_pic_get_number(frame->opaque, &framenum); upipe_dbg_va(upipe, "Allocating frame for %u (%p) - %ux%u", framenum, frame->opaque, frame->width, frame->height); if (unlikely(!upipe_avcdec->pixfmt)) { upipe_avcdec->pixfmt = upipe_av_pixfmt_from_ubuf_mgr(upipe_avcdec->ubuf_mgr); if (unlikely(!upipe_avcdec->pixfmt)) { upipe_err_va(upipe, "frame format of ubuf manager not recognized"); return 0; } } if (context->pix_fmt != *upipe_avcdec->pixfmt->pixfmt) { upipe_err_va(upipe, "frame format not compatible (%s != %s", av_get_pix_fmt_name(context->pix_fmt), av_get_pix_fmt_name(*upipe_avcdec->pixfmt->pixfmt)); return 0; } planes = upipe_avcdec->pixfmt->planes; /* direct rendering - allocate ubuf pic */ if (upipe_avcdec->context->codec->capabilities & CODEC_CAP_DR1) { width_aligned = context->width; height_aligned = context->height; /* use avcodec width/height alignement, then resize pic */ avcodec_align_dimensions(context, &width_aligned, &height_aligned); ubuf_pic = ubuf_pic_alloc(upipe_avcdec->ubuf_mgr, width_aligned, height_aligned); if (likely(ubuf_pic)) { ubuf_pic_resize(ubuf_pic, 0, 0, context->width, context->height); uref_attach_ubuf(frame->opaque, ubuf_pic); for (i=0; i < 4 && planes[i].chroma; i++) { ubuf_pic_plane_write(ubuf_pic, planes[i].chroma, 0, 0, -1, -1, &frame->data[i]); ubuf_pic_plane_size(ubuf_pic, planes[i].chroma, &stride, NULL, NULL, NULL); frame->linesize[i] = stride; } frame->extended_data = frame->data; frame->type = FF_BUFFER_TYPE_USER; return 1; /* success */ } else { upipe_dbg_va(upipe, "ubuf_pic_alloc(%d, %d) failed, fallback", width_aligned, height_aligned); } } /* default : DR failed or not available */ return avcodec_default_get_buffer(context, frame); }
/***************************************************************************** * ffmpeg_GetFrameBuf: callback used by ffmpeg to get a frame buffer. ***************************************************************************** * It is used for direct rendering as well as to get the right PTS for each * decoded picture (even in indirect rendering mode). *****************************************************************************/ static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context, AVFrame *p_ff_pic ) { decoder_t *p_dec = (decoder_t *)p_context->opaque; decoder_sys_t *p_sys = p_dec->p_sys; picture_t *p_pic; /* Set picture PTS */ if( p_sys->input_pts ) { p_ff_pic->pts = p_sys->input_pts; } else if( p_sys->input_dts ) { /* Some demuxers only set the dts so let's try to find a useful * timestamp from this */ if( !p_context->has_b_frames || !p_sys->b_has_b_frames || !p_ff_pic->reference || !p_sys->i_pts ) { p_ff_pic->pts = p_sys->input_dts; } else p_ff_pic->pts = 0; } else p_ff_pic->pts = 0; if( p_sys->i_pts ) /* make sure 1st frame has a pts > 0 */ { p_sys->input_pts = p_sys->input_dts = 0; } p_ff_pic->opaque = 0; /* Not much to do in indirect rendering mode */ if( !p_sys->b_direct_rendering || p_sys->b_pp ) { return avcodec_default_get_buffer( p_context, p_ff_pic ); } /* Some codecs set pix_fmt only after the 1st frame has been decoded, * so this check is necessary. */ if( !ffmpeg_PixFmtToChroma( p_context->pix_fmt ) || p_sys->p_context->width % 16 || p_sys->p_context->height % 16 ) { msg_Dbg( p_dec, "disabling direct rendering" ); p_sys->b_direct_rendering = 0; return avcodec_default_get_buffer( p_context, p_ff_pic ); } /* Get a new picture */ //p_sys->p_vout->render.b_allow_modify_pics = 0; p_pic = ffmpeg_NewPictBuf( p_dec, p_sys->p_context ); if( !p_pic ) { p_sys->b_direct_rendering = 0; return avcodec_default_get_buffer( p_context, p_ff_pic ); } p_sys->p_context->draw_horiz_band = NULL; p_ff_pic->opaque = (void*)p_pic; p_ff_pic->type = FF_BUFFER_TYPE_USER; p_ff_pic->data[0] = p_pic->p[0].p_pixels; p_ff_pic->data[1] = p_pic->p[1].p_pixels; p_ff_pic->data[2] = p_pic->p[2].p_pixels; p_ff_pic->data[3] = NULL; /* alpha channel but I'm not sure */ p_ff_pic->linesize[0] = p_pic->p[0].i_pitch; p_ff_pic->linesize[1] = p_pic->p[1].i_pitch; p_ff_pic->linesize[2] = p_pic->p[2].i_pitch; p_ff_pic->linesize[3] = 0; if( p_ff_pic->reference != 0 ) { p_dec->pf_picture_link( p_dec, p_pic ); } /* FIXME what is that, should give good value */ p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg return 0; }
static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context, AVFrame *p_ff_pic ) { decoder_t *p_dec = (decoder_t *)p_context->opaque; decoder_sys_t *p_sys = p_dec->p_sys; picture_t *p_pic; /* Set picture PTS */ ffmpeg_SetFrameBufferPts( p_dec, p_ff_pic ); /* */ p_ff_pic->opaque = NULL; if( p_sys->p_va ) { #ifdef HAVE_AVCODEC_VA /* hwaccel_context is not present in old fffmpeg version */ if( vlc_va_Setup( p_sys->p_va, &p_sys->p_context->hwaccel_context, &p_dec->fmt_out.video.i_chroma, p_sys->p_context->width, p_sys->p_context->height ) ) { msg_Err( p_dec, "vlc_va_Setup failed" ); return -1; } #else assert(0); #endif /* */ p_ff_pic->type = FF_BUFFER_TYPE_USER; /* FIXME what is that, should give good value */ p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg if( vlc_va_Get( p_sys->p_va, p_ff_pic ) ) { msg_Err( p_dec, "VaGrabSurface failed" ); return -1; } return 0; } else if( !p_sys->b_direct_rendering ) { /* Not much to do in indirect rendering mode. */ return avcodec_default_get_buffer( p_context, p_ff_pic ); } /* Some codecs set pix_fmt only after the 1st frame has been decoded, * so we need to check for direct rendering again. */ int i_width = p_sys->p_context->width; int i_height = p_sys->p_context->height; avcodec_align_dimensions( p_sys->p_context, &i_width, &i_height ); if( GetVlcChroma( &p_dec->fmt_out.video, p_context->pix_fmt ) != VLC_SUCCESS || p_context->pix_fmt == PIX_FMT_PAL8 ) goto no_dr; p_dec->fmt_out.i_codec = p_dec->fmt_out.video.i_chroma; /* Get a new picture */ p_pic = ffmpeg_NewPictBuf( p_dec, p_sys->p_context ); if( !p_pic ) goto no_dr; bool b_compatible = true; if( p_pic->p[0].i_pitch / p_pic->p[0].i_pixel_pitch < i_width || p_pic->p[0].i_lines < i_height ) b_compatible = false; for( int i = 0; i < p_pic->i_planes && b_compatible; i++ ) { unsigned i_align; switch( p_sys->i_codec_id ) { case CODEC_ID_SVQ1: case CODEC_ID_VP5: case CODEC_ID_VP6: case CODEC_ID_VP6F: case CODEC_ID_VP6A: i_align = 16; break; default: i_align = i == 0 ? 16 : 8; break; } if( p_pic->p[i].i_pitch % i_align ) b_compatible = false; if( (intptr_t)p_pic->p[i].p_pixels % i_align ) b_compatible = false; } if( p_context->pix_fmt == PIX_FMT_YUV422P && b_compatible ) { if( 2 * p_pic->p[1].i_pitch != p_pic->p[0].i_pitch || 2 * p_pic->p[2].i_pitch != p_pic->p[0].i_pitch ) b_compatible = false; } if( !b_compatible ) { decoder_DeletePicture( p_dec, p_pic ); goto no_dr; } if( p_sys->i_direct_rendering_used != 1 ) { msg_Dbg( p_dec, "using direct rendering" ); p_sys->i_direct_rendering_used = 1; } p_sys->p_context->draw_horiz_band = NULL; p_ff_pic->opaque = (void*)p_pic; p_ff_pic->type = FF_BUFFER_TYPE_USER; p_ff_pic->data[0] = p_pic->p[0].p_pixels; p_ff_pic->data[1] = p_pic->p[1].p_pixels; p_ff_pic->data[2] = p_pic->p[2].p_pixels; p_ff_pic->data[3] = NULL; /* alpha channel but I'm not sure */ p_ff_pic->linesize[0] = p_pic->p[0].i_pitch; p_ff_pic->linesize[1] = p_pic->p[1].i_pitch; p_ff_pic->linesize[2] = p_pic->p[2].i_pitch; p_ff_pic->linesize[3] = 0; decoder_LinkPicture( p_dec, p_pic ); /* FIXME what is that, should give good value */ p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg return 0; no_dr: if( p_sys->i_direct_rendering_used != 0 ) { msg_Warn( p_dec, "disabling direct rendering" ); p_sys->i_direct_rendering_used = 0; } return avcodec_default_get_buffer( p_context, p_ff_pic ); }