[FFmpeg-devel] [PATCH 3/4] avdevice/decklink_enc: convert AVFMT_RAWPICTURE to AV_CODEC_ID_WRAPPED_AVFRAME
wm4
nfxjfg at googlemail.com
Thu Feb 23 22:58:31 EET 2017
On Wed, 22 Feb 2017 23:46:51 +0100
Marton Balint <cus at passwd.hu> wrote:
> Signed-off-by: Marton Balint <cus at passwd.hu>
> ---
> libavdevice/decklink_enc.cpp | 78 +++++++++++++++++++++-----------------------
> libavdevice/decklink_enc_c.c | 4 +--
> libavdevice/version.h | 4 +--
> 3 files changed, 42 insertions(+), 44 deletions(-)
>
> diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp
> index 8fb6a9c..8892d19 100644
> --- a/libavdevice/decklink_enc.cpp
> +++ b/libavdevice/decklink_enc.cpp
> @@ -28,6 +28,7 @@ extern "C" {
> #include "libavformat/avformat.h"
> #include "libavformat/internal.h"
> #include "libavutil/imgutils.h"
> +#include "libavutil/atomic.h"
> }
>
> #include "decklink_common.h"
> @@ -38,33 +39,43 @@ extern "C" {
> class decklink_frame : public IDeckLinkVideoFrame
> {
> public:
> - decklink_frame(struct decklink_ctx *ctx, AVFrame *avframe, long width,
> - long height, void *buffer) :
> - _ctx(ctx), _avframe(avframe), _width(width),
> - _height(height), _buffer(buffer), _refs(0) { }
> -
> - virtual long STDMETHODCALLTYPE GetWidth (void) { return _width; }
> - virtual long STDMETHODCALLTYPE GetHeight (void) { return _height; }
> - virtual long STDMETHODCALLTYPE GetRowBytes (void) { return _width<<1; }
> + decklink_frame(struct decklink_ctx *ctx, AVFrame *avframe) :
> + _ctx(ctx), _avframe(avframe), _refs(1) { }
> +
> + virtual long STDMETHODCALLTYPE GetWidth (void) { return _avframe->width; }
> + virtual long STDMETHODCALLTYPE GetHeight (void) { return _avframe->height; }
> + virtual long STDMETHODCALLTYPE GetRowBytes (void) { return _avframe->linesize[0] < 0 ? -_avframe->linesize[0] : _avframe->linesize[0]; }
> virtual BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat(void) { return bmdFormat8BitYUV; }
> - virtual BMDFrameFlags STDMETHODCALLTYPE GetFlags (void) { return bmdVideoOutputFlagDefault; }
> - virtual HRESULT STDMETHODCALLTYPE GetBytes (void **buffer) { *buffer = _buffer; return S_OK; }
> + virtual BMDFrameFlags STDMETHODCALLTYPE GetFlags (void) { return _avframe->linesize[0] < 0 ? bmdFrameFlagFlipVertical : bmdFrameFlagDefault; }
> + virtual HRESULT STDMETHODCALLTYPE GetBytes (void **buffer)
> + {
> + if (_avframe->linesize[0] < 0)
> + *buffer = (void *)(_avframe->data[0] + _avframe->linesize[0] * (_avframe->height - 1));
> + else
> + *buffer = (void *)(_avframe->data[0]);
> + return S_OK;
> + }
>
> virtual HRESULT STDMETHODCALLTYPE GetTimecode (BMDTimecodeFormat format, IDeckLinkTimecode **timecode) { return S_FALSE; }
> virtual HRESULT STDMETHODCALLTYPE GetAncillaryData(IDeckLinkVideoFrameAncillary **ancillary) { return S_FALSE; }
>
> virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv) { return E_NOINTERFACE; }
> - virtual ULONG STDMETHODCALLTYPE AddRef(void) { return ++_refs; }
> - virtual ULONG STDMETHODCALLTYPE Release(void) { if (!--_refs) {delete this; return 0;} return _refs; }
> + virtual ULONG STDMETHODCALLTYPE AddRef(void) { return avpriv_atomic_int_add_and_fetch(&_refs, 1); }
> + virtual ULONG STDMETHODCALLTYPE Release(void)
> + {
> + int ret = avpriv_atomic_int_add_and_fetch(&_refs, -1);
> + if (!ret) {
> + av_frame_free(&_avframe);
Wouldn't this normally be in a constructor? OK, probably doesn't matter.
> + delete this;
> + }
> + return ret;
> + }
>
> struct decklink_ctx *_ctx;
> AVFrame *_avframe;
>
> private:
> - long _width;
> - long _height;
> - void *_buffer;
> - int _refs;
> + volatile int _refs;
> };
>
> class decklink_output_callback : public IDeckLinkVideoOutputCallback
> @@ -76,7 +87,7 @@ public:
> struct decklink_ctx *ctx = frame->_ctx;
> AVFrame *avframe = frame->_avframe;
>
> - av_frame_free(&avframe);
> + av_frame_unref(avframe);
>
> sem_post(&ctx->semaphore);
>
> @@ -209,41 +220,27 @@ static int decklink_write_video_packet(AVFormatContext *avctx, AVPacket *pkt)
> {
> struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data;
> struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
> - AVPicture *avpicture = (AVPicture *) pkt->data;
> - AVFrame *avframe, *tmp;
> + AVFrame *avframe, *tmp = (AVFrame *)pkt->data;
> decklink_frame *frame;
> buffercount_type buffered;
> HRESULT hr;
>
> - /* HACK while av_uncoded_frame() isn't implemented */
> - int ret;
> -
> - tmp = av_frame_alloc();
> - if (!tmp)
> - return AVERROR(ENOMEM);
> - tmp->format = AV_PIX_FMT_UYVY422;
> - tmp->width = ctx->bmd_width;
> - tmp->height = ctx->bmd_height;
> - ret = av_frame_get_buffer(tmp, 32);
> - if (ret < 0) {
> - av_frame_free(&tmp);
> - return ret;
> + if (tmp->format != AV_PIX_FMT_UYVY422 ||
> + tmp->width != ctx->bmd_width ||
> + tmp->height != ctx->bmd_height) {
> + av_log(avctx, AV_LOG_ERROR, "Got a frame with invalid pixel format or dimension.\n");
> + return AVERROR(EINVAL);
> }
> - av_image_copy(tmp->data, tmp->linesize, (const uint8_t **) avpicture->data,
> - avpicture->linesize, (AVPixelFormat) tmp->format, tmp->width,
> - tmp->height);
> avframe = av_frame_clone(tmp);
> - av_frame_free(&tmp);
> if (!avframe) {
> av_log(avctx, AV_LOG_ERROR, "Could not clone video frame.\n");
> return AVERROR(EIO);
> }
> - /* end HACK */
>
> - frame = new decklink_frame(ctx, avframe, ctx->bmd_width, ctx->bmd_height,
> - (void *) avframe->data[0]);
> + frame = new decklink_frame(ctx, avframe);
> if (!frame) {
> av_log(avctx, AV_LOG_ERROR, "Could not create new frame.\n");
> + av_frame_free(&avframe);
> return AVERROR(EIO);
> }
>
> @@ -254,10 +251,11 @@ static int decklink_write_video_packet(AVFormatContext *avctx, AVPacket *pkt)
> hr = ctx->dlo->ScheduleVideoFrame((struct IDeckLinkVideoFrame *) frame,
> pkt->pts * ctx->bmd_tb_num,
> ctx->bmd_tb_num, ctx->bmd_tb_den);
> + /* Pass ownership to DeckLink, or release on failure */
> + frame->Release();
> if (hr != S_OK) {
> av_log(avctx, AV_LOG_ERROR, "Could not schedule video frame."
> " error %08x.\n", (uint32_t) hr);
> - frame->Release();
> return AVERROR(EIO);
> }
>
> diff --git a/libavdevice/decklink_enc_c.c b/libavdevice/decklink_enc_c.c
> index c3c9018..03734f8 100644
> --- a/libavdevice/decklink_enc_c.c
> +++ b/libavdevice/decklink_enc_c.c
> @@ -46,9 +46,9 @@ AVOutputFormat ff_decklink_muxer = {
> .name = "decklink",
> .long_name = NULL_IF_CONFIG_SMALL("Blackmagic DeckLink output"),
> .audio_codec = AV_CODEC_ID_PCM_S16LE,
> - .video_codec = AV_CODEC_ID_RAWVIDEO,
> + .video_codec = AV_CODEC_ID_WRAPPED_AVFRAME,
> .subtitle_codec = AV_CODEC_ID_NONE,
> - .flags = AVFMT_NOFILE | AVFMT_RAWPICTURE,
> + .flags = AVFMT_NOFILE,
> .priv_class = &decklink_muxer_class,
> .priv_data_size = sizeof(struct decklink_cctx),
> .write_header = ff_decklink_write_header,
> diff --git a/libavdevice/version.h b/libavdevice/version.h
> index ceec2d4..a58cb0e 100644
> --- a/libavdevice/version.h
> +++ b/libavdevice/version.h
> @@ -28,8 +28,8 @@
> #include "libavutil/version.h"
>
> #define LIBAVDEVICE_VERSION_MAJOR 57
> -#define LIBAVDEVICE_VERSION_MINOR 2
> -#define LIBAVDEVICE_VERSION_MICRO 101
> +#define LIBAVDEVICE_VERSION_MINOR 3
> +#define LIBAVDEVICE_VERSION_MICRO 100
>
> #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
> LIBAVDEVICE_VERSION_MINOR, \
Can't say much about the rest of the patch, but it looks reasonable.
And I really like that it gets rid of the last use of RAWPICTURE.
More information about the ffmpeg-devel
mailing list