[FFmpeg-devel] [PATCH 2/2] lavd: add decklink output device

Ramiro Polla ramiro.polla at gmail.com
Sun Feb 9 02:09:18 CET 2014


2014-02-08 21:38 GMT-02:00 Michael Niedermayer <michaelni at gmx.at>:
> On Sat, Feb 08, 2014 at 06:05:43PM -0200, Ramiro Polla wrote:
>> 2014-01-13 21:08 GMT-02:00 Reimar Döffinger <Reimar.Doeffinger at gmx.de>:
>> > On 13.01.2014, at 04:22, Ramiro Polla <ramiro.polla at gmail.com> wrote:
>> >> On Sat, Dec 28, 2013 at 6:31 PM, Reimar Döffinger
>> >> <Reimar.Doeffinger at gmx.de> wrote:
>> >>> On Sat, Dec 28, 2013 at 05:06:16PM -0200, Ramiro Polla wrote:
>> >>>> Hi Reimar,
>> >>>>
>> >>>> On Sat, Dec 28, 2013 at 1:23 PM, Reimar Döffinger
>> >>>> <Reimar.Doeffinger at gmx.de> wrote:
>> >>>>> On 26.12.2013, at 02:44, Ramiro Polla <ramiro.polla at gmail.com> wrote:
>> >>>>>> Attached patch adds decklink output support to lavd. Works under Linux
>> >>>>>> and Windows.
>> >>>>>
>> >>>>> Maybe a bit crazy, but how about splitting the C++ part out even more?
>> >>>>> So that we can use designated initializers like for all other demuxers.
>> >>>>> Otherwise it will break as soon as we add a new field in the middle, and in addition unless you add FATE testing that works without the hardware/library "nobody" will even notice.
>> >>>>
>> >>>> I thought about so too. On Windows it is possible to use COBJMACROS
>> >>>> and write the code in C. But for Linux only a C++ interface is
>> >>>> provided. What do you think about putting just the AVOption, AVClass
>> >>>> and AVOutputFormat in a C file?
>> >>>
>> >>> Yes, either that or basically do a C++-to-C wrapper for the library.
>> >>> I guess both will look quite similar.
>> >>> As said, not sure if it's really worth it, but it _sounds_ better so
>> >>> far.
>> >>
>> >> In ff_decklink_muxer, there's a sizeof(struct decklink_ctx), which
>> >> contains a class* inside it. So that has to be c++ unless we make some
>> >> hacks using void* or somesuch. Ideas?
>> >
>> > Void * should work fine.
>> > You can also use an opaque struct decklink_stuff that is only fully declared in the C++ part and contains all the classes.
>> > Means an additional allocation and deallocation for that sub-part though.
>>
>> It turns out the decklink headers are only half smart when dealing
>> with C code (some are extern'd, some are not). New attached patch
>> splits into C and C++ files with extra decklink context struct.
>
> [...]
>> +static int decklink_setup_audio(AVFormatContext *avctx, AVStream *st)
>> +{
>> +    struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data;
>> +    struct decklink_ctx *ctx = (struct decklink_ctx *) cctx->ctx;
>> +    AVCodecContext *c = st->codec;
>> +
>> +    if (ctx->audio) {
>> +        av_log(avctx, AV_LOG_ERROR, "Only one audio stream is supported!\n");
>> +        return 0;
>> +    }
>> +    if (c->sample_rate != 48000) {
>> +        av_log(avctx, AV_LOG_ERROR, "Unsupported sample rate!"
>> +               " Only 48kHz is supported.\n");
>> +        return 0;
>> +    }
>> +    if (c->channels != 2 && c->channels != 8) {
>> +        av_log(avctx, AV_LOG_ERROR, "Unsupported number of channels!"
>> +               " Only stereo and 7.1 are supported.\n");
>> +        return 0;
>> +    }
>> +    if (ctx->dlo->EnableAudioOutput(bmdAudioSampleRate48kHz,
>> +                                    bmdAudioSampleType16bitInteger,
>> +                                    c->channels,
>> +                                    bmdAudioOutputStreamTimestamped) != S_OK) {
>> +        av_log(avctx, AV_LOG_ERROR, "Could not enable audio output!\n");
>> +        return 0;
>> +    }
>> +    if (ctx->dlo->BeginAudioPreroll() != S_OK) {
>> +        av_log(avctx, AV_LOG_ERROR, "Could not begin audio preroll!\n");
>> +        return 0;
>> +    }
>> +
>> +    /* The device expects the sample rate to be fixed. */
>> +    avpriv_set_pts_info(st, 64, 1, c->sample_rate);
>> +    ctx->channels = c->channels;
>> +
>> +    ctx->audio = 1;
>> +
>> +    return 1;
>> +}
>> +
>> +av_cold int ff_decklink_write_trailer(AVFormatContext *avctx)
>> +{
>> +    struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data;
>> +    struct decklink_ctx *ctx = (struct decklink_ctx *) cctx->ctx;
>> +
>> +    if (ctx->playback_started) {
>> +        BMDTimeValue actual;
>> +        ctx->dlo->StopScheduledPlayback(ctx->last_pts * ctx->bmd_tb_num,
>> +                                        &actual, ctx->bmd_tb_den);
>> +        ctx->dlo->DisableVideoOutput();
>> +        if (ctx->audio)
>> +            ctx->dlo->DisableAudioOutput();
>> +    }
>> +
>> +    if (ctx->dlo)
>> +        ctx->dlo->Release();
>> +    if (ctx->dl)
>> +        ctx->dl->Release();
>> +
>> +    if (ctx->callback)
>> +        delete ctx->callback;
>> +
>> +    sem_destroy(&ctx->semaphore);
>> +
>> +    av_freep(&cctx->ctx);
>> +
>> +    return 0;
>> +}
>
> the return codes are inconsistent, this uses 0 like most of ffmpeg
> as "success" while the one aboce uses 1
> I think that could confuse a reader easily
>
>
>
> [...]
>> +int ff_decklink_write_packet(AVFormatContext *avctx, AVPacket *pkt)
>> +{
>> +    struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data;
>> +    struct decklink_ctx *ctx = (struct decklink_ctx *) cctx->ctx;
>> +    AVStream *st = avctx->streams[pkt->stream_index];
>> +
>
>> +    if (ctx->last_pts < pkt->pts)
>> +        ctx->last_pts = pkt->pts;
>
> FFMAX()
>
>
> [...]
>> diff --git a/libavdevice/decklink_enc_c.c b/libavdevice/decklink_enc_c.c
>> new file mode 100644
>> index 0000000..be4c90d
>> --- /dev/null
>> +++ b/libavdevice/decklink_enc_c.c
>> @@ -0,0 +1,55 @@
>> +/*
>> + * Blackmagic DeckLink output
>> + * Copyright (c) 2013-2014 Ramiro Polla
>> + *
>> + * This file is part of FFmpeg.
>> + *
>> + * FFmpeg is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU Lesser General Public
>> + * License as published by the Free Software Foundation; either
>> + * version 2.1 of the License, or (at your option) any later version.
>> + *
>> + * FFmpeg is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> + * Lesser General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU Lesser General Public
>> + * License along with FFmpeg; if not, write to the Free Software
>> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
>> + */
>> +
>> +#include "libavformat/avformat.h"
>> +#include "libavutil/opt.h"
>> +
>> +#include "decklink_enc.h"
>> +
>> +#define OFFSET(x) offsetof(struct decklink_cctx, x)
>> +#define ENC AV_OPT_FLAG_ENCODING_PARAM
>> +static const AVOption options[] = {
>
>> +    { "list_devices", "list available devices"  , OFFSET(list_devices), AV_OPT_TYPE_INT   , {        0   }, 0, 1, ENC },
>> +    { "list_formats", "list supported formats"  , OFFSET(list_formats), AV_OPT_TYPE_INT   , {        0   }, 0, 1, ENC },
>
> probably makes no difference but .i64 = 0

Updated.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-lavd-add-decklink-output-device.patch
Type: text/x-patch
Size: 30158 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20140208/ea3b0580/attachment.bin>


More information about the ffmpeg-devel mailing list