From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTP id 79FF145A66 for ; Mon, 13 Mar 2023 23:38:52 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 8770968BD94; Tue, 14 Mar 2023 01:38:50 +0200 (EET) Received: from iq.passwd.hu (iq.passwd.hu [217.27.212.140]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id EB18568BD24 for ; Tue, 14 Mar 2023 01:38:44 +0200 (EET) Received: from localhost (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 3192FE8913 for ; Tue, 14 Mar 2023 00:38:50 +0100 (CET) X-Virus-Scanned: amavisd-new at passwd.hu Received: from iq.passwd.hu ([127.0.0.1]) by localhost (iq.passwd.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 6LXv_MhnwGnK for ; Tue, 14 Mar 2023 00:38:48 +0100 (CET) Received: from iq (iq [217.27.212.140]) by iq.passwd.hu (Postfix) with ESMTPS id 80280E8912 for ; Tue, 14 Mar 2023 00:38:48 +0100 (CET) Date: Tue, 14 Mar 2023 00:38:48 +0100 (CET) From: Marton Balint To: FFmpeg development discussions and patches In-Reply-To: <20230309140808.5946-1-dheitmueller@ltnglobal.com> Message-ID: <9657e20-9ff0-4ee-934f-76dd9c9116de@passwd.hu> References: <20230309140808.5946-1-dheitmueller@ltnglobal.com> MIME-Version: 1.0 Subject: Re: [FFmpeg-devel] [PATCH] decklink: Add support for compressed AC-3 output over SDI X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="us-ascii"; Format="flowed" Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: On Thu, 9 Mar 2023, Devin Heitmueller wrote: > Extend the decklink output to include support for compressed AC-3, > encapsulated using the SMPTE ST 377:2015 standard. > > This functionality can be exercised by using the "copy" codec when > the input audio stream is AC-3. For example: > > ./ffmpeg -i ~/foo.ts -codec:a copy -f decklink 'UltraStudio Mini Monitor' > > Note that the default behavior continues to be to do PCM output, > which means without specifying the copy codec a stream containing > AC-3 will be decoded and downmixed to stereo audio before output. > > Signed-off-by: Devin Heitmueller > --- > libavdevice/decklink_enc.cpp | 97 ++++++++++++++++++++++++++++++------ > 1 file changed, 82 insertions(+), 15 deletions(-) > > diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp > index 8d423f6b6e..51a2bb4aad 100644 > --- a/libavdevice/decklink_enc.cpp > +++ b/libavdevice/decklink_enc.cpp > @@ -243,19 +243,32 @@ static int decklink_setup_audio(AVFormatContext *avctx, AVStream *st) > av_log(avctx, AV_LOG_ERROR, "Only one audio stream is supported!\n"); > return -1; > } > - if (c->sample_rate != 48000) { > - av_log(avctx, AV_LOG_ERROR, "Unsupported sample rate!" > - " Only 48kHz is supported.\n"); > - return -1; > - } > - if (c->ch_layout.nb_channels != 2 && c->ch_layout.nb_channels != 8 && c->ch_layout.nb_channels != 16) { > - av_log(avctx, AV_LOG_ERROR, "Unsupported number of channels!" > - " Only 2, 8 or 16 channels are supported.\n"); > + > + if (c->codec_id == AV_CODEC_ID_AC3) { > + /* Regardless of the number of channels in the codec, we're only > + using 2 SDI audio channels at 48000Hz */ > + ctx->channels = 2; > + } else if (c->codec_id == AV_CODEC_ID_PCM_S16LE) { > + if (c->sample_rate != 48000) { > + av_log(avctx, AV_LOG_ERROR, "Unsupported sample rate!" > + " Only 48kHz is supported.\n"); > + return -1; > + } > + if (c->ch_layout.nb_channels != 2 && c->ch_layout.nb_channels != 8 && c->ch_layout.nb_channels != 16) { > + av_log(avctx, AV_LOG_ERROR, "Unsupported number of channels!" > + " Only 2, 8 or 16 channels are supported.\n"); > + return -1; > + } > + ctx->channels = c->ch_layout.nb_channels; > + } else { > + av_log(avctx, AV_LOG_ERROR, "Unsupported codec specified!" > + " Only PCM_S16LE and AC-3 are supported.\n"); > return -1; > } > + > if (ctx->dlo->EnableAudioOutput(bmdAudioSampleRate48kHz, > bmdAudioSampleType16bitInteger, > - c->ch_layout.nb_channels, > + ctx->channels, > bmdAudioOutputStreamTimestamped) != S_OK) { > av_log(avctx, AV_LOG_ERROR, "Could not enable audio output!\n"); > return -1; > @@ -266,14 +279,49 @@ static int decklink_setup_audio(AVFormatContext *avctx, AVStream *st) > } > > /* The device expects the sample rate to be fixed. */ > - avpriv_set_pts_info(st, 64, 1, c->sample_rate); > - ctx->channels = c->ch_layout.nb_channels; > + avpriv_set_pts_info(st, 64, 1, bmdAudioSampleRate48kHz); I'd rather not use a BMD constant for non-BMD function. Make this 48000 or create a non-BMD 48000 constant and use it here and when checking the sample rate earlier. > > ctx->audio = 1; > > return 0; > } > > +static int create_s337_payload(AVPacket *pkt, enum AVCodecID codec_id, uint8_t **outbuf, int *outsize) > +{ > + uint8_t *s337_payload; > + uint8_t *s337_payload_start; > + int i; > + > + if (codec_id != AV_CODEC_ID_AC3) > + return AVERROR(EINVAL); Use the PutByteContext for this function. > + > + /* Encapsulate AC3 syncframe into SMPTE 337 packet */ > + *outsize = pkt->size + 8; > + s337_payload = (uint8_t *) av_mallocz(*outsize); > + if (s337_payload == NULL) > + return AVERROR(ENOMEM); > + > + /* Construct SMPTE S337 Burst preamble */ > + s337_payload[0] = 0x72; /* Sync Word 1 */ > + s337_payload[1] = 0xf8; /* Sync Word 1 */ > + s337_payload[2] = 0x1f; /* Sync Word 1 */ > + s337_payload[3] = 0x4e; /* Sync Word 1 */ > + s337_payload[4] = 0x01; /* Burst Info, including data type (1=ac3) */ > + s337_payload[5] = 0x00; > + uint16_t bitcount = pkt->size * 8; > + s337_payload[6] = bitcount & 0xff; /* Length code */ > + s337_payload[7] = bitcount >> 8; /* Length code */ > + s337_payload_start = &s337_payload[8]; > + for (i = 0; i < pkt->size; i += 2) { > + s337_payload_start[0] = pkt->data[i+1]; > + s337_payload_start[1] = pkt->data[i]; > + s337_payload_start += 2; > + } > + > + *outbuf = s337_payload; > + return 0; > +} > + > av_cold int ff_decklink_write_trailer(AVFormatContext *avctx) > { > struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; > @@ -531,21 +579,40 @@ static int decklink_write_audio_packet(AVFormatContext *avctx, AVPacket *pkt) > { > struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; > struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx; > - int sample_count = pkt->size / (ctx->channels << 1); > + AVStream *st = avctx->streams[pkt->stream_index]; > + int sample_count; > uint32_t buffered; > + uint8_t *outbuf = NULL; > + int ret = 0; > > ctx->dlo->GetBufferedAudioSampleFrameCount(&buffered); > if (pkt->pts > 1 && !buffered) > av_log(avctx, AV_LOG_WARNING, "There's no buffered audio." > " Audio will misbehave!\n"); > > - if (ctx->dlo->ScheduleAudioSamples(pkt->data, sample_count, pkt->pts, > + if (st->codecpar->codec_id == AV_CODEC_ID_AC3) { > + /* Encapsulate AC3 syncframe into SMPTE 337 packet */ > + int outbuf_size; > + ret = create_s337_payload(pkt, st->codecpar->codec_id, > + &outbuf, &outbuf_size); Can't you create a buffer on the stack instead of using a dynamic memory allocation for each frame? I guess the S337 packet should never exceed the uncompressed size, but AC3 might have even more strict frame size limits. > + if (ret) > + return ret; > + sample_count = outbuf_size / 4; How is it ensured that enough raw audio data is provided for Decklink? Or we provide "sparse" audio data to the decklink API, and decklink will pad the audio with silence based on the packet timestamps? > + } else { > + sample_count = pkt->size / (ctx->channels << 1); > + outbuf = pkt->data; > + } > + > + if (ctx->dlo->ScheduleAudioSamples(outbuf, sample_count, pkt->pts, > bmdAudioSampleRate48kHz, NULL) != S_OK) { > av_log(avctx, AV_LOG_ERROR, "Could not schedule audio samples.\n"); > - return AVERROR(EIO); > + ret = AVERROR(EIO); > } > > - return 0; > + if (st->codecpar->codec_id == AV_CODEC_ID_AC3) > + av_freep(&outbuf); > + > + return ret; > } Thanks, Marton _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".