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 internal.h first to avoid conflict between winsock.h (used by
26 * DeckLink headers) and winsock2.h (used by libavformat) in MSVC++ builds */
27 extern "C" {
29 }
30
31 #include <DeckLinkAPI.h>
32
33 extern "C" {
37 }
38
41
42
43 /* DeckLink callback class declaration */
45 {
46 public:
51
55 {
58 else
59 return ((
GetWidth() + 47) / 48) * 128;
60 }
62 {
64 return bmdFormat8BitYUV;
65 else
66 return bmdFormat10BitYUV;
67 }
68 virtual BMDFrameFlags STDMETHODCALLTYPE
GetFlags (
void)
69 {
71 return _avframe->
linesize[0] < 0 ? bmdFrameFlagFlipVertical : bmdFrameFlagDefault;
72 else
73 return bmdFrameFlagDefault;
74 }
75
77 {
81 else
83 } else {
85 }
87 }
88
91
95 {
97 if (!ret) {
100 delete this;
101 }
102 return ret;
103 }
104
111
112 private:
114 };
115
117 {
118 public:
120 {
123
128
133
135 }
140 };
141
143 {
147
150 return -1;
151 }
152
156 " Only AV_PIX_FMT_UYVY422 is supported.\n");
157 return -1;
158 }
161 " Only V210 and wrapped frame with AV_PIX_FMT_UYVY422 are supported.\n");
162 return -1;
163 }
164
167 return -1;
168 }
172 " Check available formats with -list_formats 1.\n");
173 return -1;
174 }
175 if (
ctx->dlo->EnableVideoOutput(
ctx->bmd_mode,
176 bmdVideoOutputFlagDefault) !=
S_OK) {
178 return -1;
179 }
180
181 /* Set callback. */
183 ctx->dlo->SetScheduledFrameCompletionCallback(
ctx->output_callback);
184
187 ctx->frames_preroll /= 1000;
188
189 /* Buffer twice as many frames as the preroll. */
190 ctx->frames_buffer =
ctx->frames_preroll * 2;
191 ctx->frames_buffer =
FFMIN(
ctx->frames_buffer, 60);
194 ctx->frames_buffer_available_spots =
ctx->frames_buffer;
195
196 /* The device expects the framerate to be fixed. */
198
200
201 return 0;
202 }
203
205 {
209
212 return -1;
213 }
216 " Only 48kHz is supported.\n");
217 return -1;
218 }
221 " Only 2, 8 or 16 channels are supported.\n");
222 return -1;
223 }
224 if (
ctx->dlo->EnableAudioOutput(bmdAudioSampleRate48kHz,
225 bmdAudioSampleType16bitInteger,
227 bmdAudioOutputStreamTimestamped) !=
S_OK) {
229 return -1;
230 }
231 if (
ctx->dlo->BeginAudioPreroll() !=
S_OK) {
233 return -1;
234 }
235
236 /* The device expects the sample rate to be fixed. */
239
241
242 return 0;
243 }
244
246 {
249
250 if (
ctx->playback_started) {
251 BMDTimeValue actual;
252 ctx->dlo->StopScheduledPlayback(
ctx->last_pts *
ctx->bmd_tb_num,
253 &actual,
ctx->bmd_tb_den);
254 ctx->dlo->DisableVideoOutput();
256 ctx->dlo->DisableAudioOutput();
257 }
258
260
261 if (
ctx->output_callback)
262 delete ctx->output_callback;
263
266
268
269 return 0;
270 }
271
273 {
282
285 tmp->width !=
ctx->bmd_width ||
286 tmp->height !=
ctx->bmd_height) {
289 }
290
292 if (!avframe) {
295 }
296
298 } else {
300 if (!avpacket) {
303 }
304
306 }
307
313 }
314
315 /* Always keep at most one second of frames buffered. */
317 while (
ctx->frames_buffer_available_spots == 0) {
319 }
320 ctx->frames_buffer_available_spots--;
322
323 /* Schedule frame for playback. */
324 hr =
ctx->dlo->ScheduleVideoFrame((
class IDeckLinkVideoFrame *)
frame,
325 pkt->
pts *
ctx->bmd_tb_num,
326 ctx->bmd_tb_num,
ctx->bmd_tb_den);
327 /* Pass ownership to DeckLink, or release on failure */
331 " error %08x.\n", (uint32_t) hr);
333 }
334
335 ctx->dlo->GetBufferedVideoFrameCount(&buffered);
337 if (pkt->
pts > 2 && buffered <= 2)
339 " Video may misbehave!\n");
340
341 /* Preroll video frames. */
342 if (!
ctx->playback_started && pkt->
pts >
ctx->frames_preroll) {
344 if (
ctx->audio &&
ctx->dlo->EndAudioPreroll() !=
S_OK) {
347 }
349 if (
ctx->dlo->StartScheduledPlayback(0,
ctx->bmd_tb_den, 1.0) !=
S_OK) {
352 }
353 ctx->playback_started = 1;
354 }
355
356 return 0;
357 }
358
360 {
363 int sample_count = pkt->
size / (
ctx->channels << 1);
365
366 ctx->dlo->GetBufferedAudioSampleFrameCount(&buffered);
367 if (pkt->
pts > 1 && !buffered)
369 " Audio will misbehave!\n");
370
371 if (
ctx->dlo->ScheduleAudioSamples(pkt->
data, sample_count, pkt->
pts,
372 bmdAudioSampleRate48kHz,
NULL) !=
S_OK) {
375 }
376
377 return 0;
378 }
379
380 extern "C" {
381
383 {
387 int ret;
388
396
397 /* List available devices and exit. */
398 if (
ctx->list_devices) {
401 }
402
404 if (ret < 0)
405 return ret;
406
407 /* Get output device. */
408 if (
ctx->dl->QueryInterface(IID_IDeckLinkOutput, (
void **) &
ctx->dlo) !=
S_OK) {
413 }
414
415 /* List supported formats. */
416 if (
ctx->list_formats) {
420 }
421
422 /* Setup streams. */
433 } else {
436 }
437 }
438
439 return 0;
440
443 return ret;
444 }
445
447 {
451
453
458
460 }
461
463 {
465 }
466
467 } /* extern "C" */
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
decklink_frame(struct decklink_ctx *ctx, AVFrame *avframe, AVCodecID codec_id, int height, int width)
enum AVFieldOrder field_order
Video only.
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
static const char * format[]
This structure describes decoded (raw) audio or video data.
#define pthread_mutex_lock(a)
static av_always_inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
virtual long STDMETHODCALLTYPE GetWidth(void)
#define AV_LOG_WARNING
Something somehow does not look correct.
static int decklink_setup_video(AVFormatContext *avctx, AVStream *st)
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
static int decklink_write_audio_packet(AVFormatContext *avctx, AVPacket *pkt)
decklink_frame(struct decklink_ctx *ctx, AVPacket *avpacket, AVCodecID codec_id, int height, int width)
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...
static av_always_inline int pthread_cond_destroy(pthread_cond_t *cond)
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)
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv)
virtual long STDMETHODCALLTYPE GetHeight(void)
AVStream ** streams
A list of all streams in the file.
void ff_decklink_list_devices_legacy(AVFormatContext *avctx, int show_inputs, int show_outputs)
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)
int frames_buffer_available_spots
int ff_decklink_list_devices(AVFormatContext *avctx, struct AVDeviceInfoList *device_list, int show_inputs, int show_outputs)
static int decklink_setup_audio(AVFormatContext *avctx, AVStream *st)
Main libavdevice API header.
virtual ULONG STDMETHODCALLTYPE Release(void)
AVCodecID
Identify the syntax and semantics of the bitstream.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
virtual HRESULT STDMETHODCALLTYPE ScheduledPlaybackHasStopped(void)
AVPacket * av_packet_clone(const AVPacket *src)
Create a new packet that references the same data as src.
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
char * url
input or output URL.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
int ff_decklink_list_output_devices(AVFormatContext *avctx, struct AVDeviceInfoList *device_list)
enum AVMediaType codec_type
General type of the encoded data.
virtual BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat(void)
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
int ff_decklink_set_configs(AVFormatContext *avctx, decklink_direction_t direction)
struct decklink_ctx * _ctx
av_cold int ff_decklink_write_header(AVFormatContext *avctx)
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
uint32_t buffercount_type
int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direction)
virtual long STDMETHODCALLTYPE GetRowBytes(void)
#define pthread_mutex_unlock(a)
Passthrough codec, AVFrames wrapped in AVPacket.
#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.
virtual ULONG STDMETHODCALLTYPE AddRef(void)
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
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)
static av_always_inline int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
virtual ULONG STDMETHODCALLTYPE AddRef(void)
static av_always_inline int pthread_cond_broadcast(pthread_cond_t *cond)
void * priv_data
Format private data.
int ff_decklink_write_packet(AVFormatContext *avctx, AVPacket *pkt)
AVCodecParameters * codecpar
Codec parameters associated with this stream.
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...
virtual ULONG STDMETHODCALLTYPE Release(void)