1 /*
2 * Blackmagic DeckLink output
3 * Copyright (c) 2013-2014 Ramiro Polla
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include <atomic>
23 using std::atomic;
24
25 #include <DeckLinkAPI.h>
26
27 #include <pthread.h>
29
30 extern "C" {
34 }
35
38
39
40 /* DeckLink callback class declaration */
42 {
43 public:
46
50 virtual BMDPixelFormat STDMETHODCALLTYPE
GetPixelFormat(
void) {
return bmdFormat8BitYUV; }
51 virtual BMDFrameFlags STDMETHODCALLTYPE
GetFlags (
void) {
return _avframe->
linesize[0] < 0 ? bmdFrameFlagFlipVertical : bmdFrameFlagDefault; }
53 {
56 else
59 }
60
63
67 {
69 if (!ret) {
71 delete this;
72 }
73 return ret;
74 }
75
78
79 private:
81 };
82
84 {
85 public:
87 {
91
93
95
97 }
102 };
103
105 {
109
112 return -1;
113 }
114
117 " Only AV_PIX_FMT_UYVY422 is supported.\n");
118 return -1;
119 }
123 " Check available formats with -list_formats 1.\n");
124 return -1;
125 }
126 if (
ctx->dlo->EnableVideoOutput(
ctx->bmd_mode,
127 bmdVideoOutputFlagDefault) !=
S_OK) {
129 return -1;
130 }
131
132 /* Set callback. */
134 ctx->dlo->SetScheduledFrameCompletionCallback(
ctx->output_callback);
135
136 /* Start video semaphore. */
139 ctx->frames_preroll /= 1000;
140
141 /* Buffer twice as many frames as the preroll. */
142 ctx->frames_buffer =
ctx->frames_preroll * 2;
143 ctx->frames_buffer =
FFMIN(
ctx->frames_buffer, 60);
145
146 /* The device expects the framerate to be fixed. */
148
150
151 return 0;
152 }
153
155 {
159
162 return -1;
163 }
166 " Only 48kHz is supported.\n");
167 return -1;
168 }
171 " Only stereo and 7.1 are supported.\n");
172 return -1;
173 }
174 if (
ctx->dlo->EnableAudioOutput(bmdAudioSampleRate48kHz,
175 bmdAudioSampleType16bitInteger,
177 bmdAudioOutputStreamTimestamped) !=
S_OK) {
179 return -1;
180 }
181 if (
ctx->dlo->BeginAudioPreroll() !=
S_OK) {
183 return -1;
184 }
185
186 /* The device expects the sample rate to be fixed. */
189
191
192 return 0;
193 }
194
196 {
199
200 if (
ctx->playback_started) {
201 BMDTimeValue actual;
202 ctx->dlo->StopScheduledPlayback(
ctx->last_pts *
ctx->bmd_tb_num,
203 &actual,
ctx->bmd_tb_den);
204 ctx->dlo->DisableVideoOutput();
206 ctx->dlo->DisableAudioOutput();
207 }
208
210
211 if (
ctx->output_callback)
212 delete ctx->output_callback;
213
215
217
218 return 0;
219 }
220
222 {
229
235 }
237 if (!avframe) {
240 }
241
247 }
248
249 /* Always keep at most one second of frames buffered. */
251
252 /* Schedule frame for playback. */
253 hr =
ctx->dlo->ScheduleVideoFrame((
struct IDeckLinkVideoFrame *)
frame,
254 pkt->
pts *
ctx->bmd_tb_num,
255 ctx->bmd_tb_num,
ctx->bmd_tb_den);
256 /* Pass ownership to DeckLink, or release on failure */
260 " error %08x.\n", (uint32_t) hr);
262 }
263
264 ctx->dlo->GetBufferedVideoFrameCount(&buffered);
266 if (pkt->
pts > 2 && buffered <= 2)
268 " Video may misbehave!\n");
269
270 /* Preroll video frames. */
271 if (!
ctx->playback_started && pkt->
pts >
ctx->frames_preroll) {
273 if (
ctx->audio &&
ctx->dlo->EndAudioPreroll() !=
S_OK) {
276 }
278 if (
ctx->dlo->StartScheduledPlayback(0,
ctx->bmd_tb_den, 1.0) !=
S_OK) {
281 }
282 ctx->playback_started = 1;
283 }
284
285 return 0;
286 }
287
289 {
292 int sample_count = pkt->
size / (
ctx->channels << 1);
294
295 ctx->dlo->GetBufferedAudioSampleFrameCount(&buffered);
296 if (pkt->
pts > 1 && !buffered)
298 " Audio will misbehave!\n");
299
300 if (
ctx->dlo->ScheduleAudioSamples(pkt->
data, sample_count, pkt->
pts,
301 bmdAudioSampleRate48kHz,
NULL) !=
S_OK) {
304 }
305
306 return 0;
307 }
308
309 extern "C" {
310
312 {
316 int ret;
317
325
326 /* List available devices. */
327 if (
ctx->list_devices) {
330 }
331
333 if (ret < 0)
334 return ret;
335
336 /* Get output device. */
337 if (
ctx->dl->QueryInterface(IID_IDeckLinkOutput, (
void **) &
ctx->dlo) !=
S_OK) {
342 }
343
344 /* List supported formats. */
345 if (
ctx->list_formats) {
349 }
350
351 /* Setup streams. */
362 } else {
365 }
366 }
367
368 return 0;
369
372 return ret;
373 }
374
376 {
380
382
387
389 }
390
391 } /* extern "C" */
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
enum AVFieldOrder field_order
Video only.
This structure describes decoded (raw) audio or video data.
virtual long STDMETHODCALLTYPE GetWidth(void)
#define AV_LOG_WARNING
Something somehow does not look correct.
static int decklink_setup_video(AVFormatContext *avctx, AVStream *st)
static int decklink_write_audio_packet(AVFormatContext *avctx, AVPacket *pkt)
int ff_decklink_init_device(AVFormatContext *avctx, const char *name)
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
This struct describes the properties of an encoded stream.
av_cold int ff_decklink_write_trailer(AVFormatContext *avctx)
static int decklink_write_video_packet(AVFormatContext *avctx, AVPacket *pkt)
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv)
virtual long STDMETHODCALLTYPE GetHeight(void)
AVStream ** streams
A list of all streams in the file.
int ff_decklink_set_format(AVFormatContext *avctx, int width, int height, int tb_num, int tb_den, enum AVFieldOrder field_order, decklink_direction_t direction, int num)
static int decklink_setup_audio(AVFormatContext *avctx, AVStream *st)
virtual ULONG STDMETHODCALLTYPE Release(void)
int width
width and height of the video frame
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
virtual HRESULT STDMETHODCALLTYPE ScheduledPlaybackHasStopped(void)
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
enum AVMediaType codec_type
General type of the encoded data.
#define sem_destroy(psem)
virtual BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat(void)
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
char filename[1024]
input or output filename
struct decklink_ctx * _ctx
av_cold int ff_decklink_write_header(AVFormatContext *avctx)
uint32_t buffercount_type
int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direction)
virtual long STDMETHODCALLTYPE GetRowBytes(void)
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
static void error(const char *err)
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
virtual ULONG STDMETHODCALLTYPE AddRef(void)
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
int ff_decklink_list_devices(AVFormatContext *avctx)
static const char * format
virtual BMDFrameFlags STDMETHODCALLTYPE GetFlags(void)
virtual HRESULT STDMETHODCALLTYPE GetBytes(void **buffer)
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
void ff_decklink_cleanup(AVFormatContext *avctx)
int sample_rate
Audio only.
virtual HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted(IDeckLinkVideoFrame *_frame, BMDOutputFrameCompletionResult result)
virtual HRESULT STDMETHODCALLTYPE GetAncillaryData(IDeckLinkVideoFrameAncillary **ancillary)
virtual ULONG STDMETHODCALLTYPE AddRef(void)
void * priv_data
Format private data.
int ff_decklink_write_packet(AVFormatContext *avctx, AVPacket *pkt)
AVCodecParameters * codecpar
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv)
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
virtual HRESULT STDMETHODCALLTYPE GetTimecode(BMDTimecodeFormat format, IDeckLinkTimecode **timecode)
This structure stores compressed data.
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
decklink_frame(struct decklink_ctx *ctx, AVFrame *avframe)
virtual ULONG STDMETHODCALLTYPE Release(void)