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 <DeckLinkAPI.h>
23
24 #include <pthread.h>
25 #include <semaphore.h>
26
27 extern "C" {
31 }
32
35
36
37 /* DeckLink callback class declaration */
39 {
40 public:
45
49 virtual BMDPixelFormat STDMETHODCALLTYPE
GetPixelFormat(
void) {
return bmdFormat8BitYUV; }
50 virtual BMDFrameFlags STDMETHODCALLTYPE
GetFlags (
void) {
return bmdVideoOutputFlagDefault; }
52
55
59
62
63 private:
68 };
69
71 {
72 public:
74 {
78
80
82
84 }
89 };
90
92 {
96
99 return -1;
100 }
101
104 " Only AV_PIX_FMT_UYVY422 is supported.\n");
105 return -1;
106 }
110 " Check available formats with -list_formats 1.\n");
111 return -1;
112 }
113 if (
ctx->dlo->EnableVideoOutput(
ctx->bmd_mode,
114 bmdVideoOutputFlagDefault) !=
S_OK) {
116 return -1;
117 }
118
119 /* Set callback. */
121 ctx->dlo->SetScheduledFrameCompletionCallback(
ctx->output_callback);
122
123 /* Start video semaphore. */
126 ctx->frames_preroll /= 1000;
127
128 /* Buffer twice as many frames as the preroll. */
129 ctx->frames_buffer =
ctx->frames_preroll * 2;
130 ctx->frames_buffer =
FFMIN(
ctx->frames_buffer, 60);
131 sem_init(&
ctx->semaphore, 0,
ctx->frames_buffer);
132
133 /* The device expects the framerate to be fixed. */
135
137
138 return 0;
139 }
140
142 {
146
149 return -1;
150 }
153 " Only 48kHz is supported.\n");
154 return -1;
155 }
158 " Only stereo and 7.1 are supported.\n");
159 return -1;
160 }
161 if (
ctx->dlo->EnableAudioOutput(bmdAudioSampleRate48kHz,
162 bmdAudioSampleType16bitInteger,
164 bmdAudioOutputStreamTimestamped) !=
S_OK) {
166 return -1;
167 }
168 if (
ctx->dlo->BeginAudioPreroll() !=
S_OK) {
170 return -1;
171 }
172
173 /* The device expects the sample rate to be fixed. */
176
178
179 return 0;
180 }
181
183 {
186
187 if (
ctx->playback_started) {
188 BMDTimeValue actual;
189 ctx->dlo->StopScheduledPlayback(
ctx->last_pts *
ctx->bmd_tb_num,
190 &actual,
ctx->bmd_tb_den);
191 ctx->dlo->DisableVideoOutput();
193 ctx->dlo->DisableAudioOutput();
194 }
195
200
201 if (
ctx->output_callback)
202 delete ctx->output_callback;
203
204 sem_destroy(&
ctx->semaphore);
205
207
208 return 0;
209 }
210
212 {
220
221 /* HACK while av_uncoded_frame() isn't implemented */
222 int ret;
223
225 if (!tmp)
228 tmp->width =
ctx->bmd_width;
229 tmp->height =
ctx->bmd_height;
231 if (ret < 0) {
233 return ret;
234 }
237 tmp->height);
240 if (!avframe) {
243 }
244 /* end HACK */
245
247 (
void *) avframe->
data[0]);
251 }
252
253 /* Always keep at most one second of frames buffered. */
254 sem_wait(&
ctx->semaphore);
255
256 /* Schedule frame for playback. */
257 hr =
ctx->dlo->ScheduleVideoFrame((
struct IDeckLinkVideoFrame *)
frame,
258 pkt->
pts *
ctx->bmd_tb_num,
259 ctx->bmd_tb_num,
ctx->bmd_tb_den);
262 " error %08x.\n", (uint32_t) hr);
265 }
266
267 ctx->dlo->GetBufferedVideoFrameCount(&buffered);
269 if (pkt->
pts > 2 && buffered <= 2)
271 " Video may misbehave!\n");
272
273 /* Preroll video frames. */
274 if (!
ctx->playback_started && pkt->
pts >
ctx->frames_preroll) {
276 if (
ctx->audio &&
ctx->dlo->EndAudioPreroll() !=
S_OK) {
279 }
281 if (
ctx->dlo->StartScheduledPlayback(0,
ctx->bmd_tb_den, 1.0) !=
S_OK) {
284 }
285 ctx->playback_started = 1;
286 }
287
288 return 0;
289 }
290
292 {
295 int sample_count = pkt->
size / (
ctx->channels << 1);
297
298 ctx->dlo->GetBufferedAudioSampleFrameCount(&buffered);
299 if (pkt->
pts > 1 && !buffered)
301 " Audio will misbehave!\n");
302
303 if (
ctx->dlo->ScheduleAudioSamples(pkt->
data, sample_count, pkt->
pts,
304 bmdAudioSampleRate48kHz,
NULL) !=
S_OK) {
307 }
308
309 return 0;
310 }
311
312 extern "C" {
313
315 {
318 IDeckLinkDisplayModeIterator *itermode;
319 IDeckLinkIterator *iter;
320 IDeckLink *dl =
NULL;
322
330
331 iter = CreateDeckLinkIteratorInstance();
332 if (!iter) {
335 }
336
337 /* List available devices. */
338 if (
ctx->list_devices) {
341 }
342
343 /* Open device. */
344 while (iter->Next(&dl) ==
S_OK) {
345 const char *displayName;
347 if (!strcmp(avctx->
filename, displayName)) {
350 break;
351 }
353 dl->Release();
354 }
355 iter->Release();
359 }
360
361 /* Get output device. */
362 if (
ctx->dl->QueryInterface(IID_IDeckLinkOutput, (
void **) &
ctx->dlo) !=
S_OK) {
367 }
368
369 /* List supported formats. */
370 if (
ctx->list_formats) {
375 }
376
377 if (
ctx->dlo->GetDisplayModeIterator(&itermode) !=
S_OK) {
381 }
382
383 /* Setup streams. */
389 goto error;
392 goto error;
393 } else {
395 goto error;
396 }
397 }
398 itermode->Release();
399
400 return 0;
401
402 error:
403
406
408 }
409
411 {
415
417
422
424 }
425
426 } /* extern "C" */
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
This structure describes decoded (raw) audio or video data.
virtual long STDMETHODCALLTYPE GetWidth(void)
#define AV_LOG_WARNING
Something somehow does not look correct.
decklink_frame(struct decklink_ctx *ctx, AVFrame *avframe, long width, long height, void *buffer)
static int decklink_setup_video(AVFormatContext *avctx, AVStream *st)
static int decklink_write_audio_packet(AVFormatContext *avctx, AVPacket *pkt)
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
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)
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
attribute_deprecated int linesize[AV_NUM_DATA_POINTERS]
number of bytes per line
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, decklink_direction_t direction, int num)
static int decklink_setup_audio(AVFormatContext *avctx, AVStream *st)
virtual ULONG STDMETHODCALLTYPE Release(void)
#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.
virtual BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat(void)
void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4], const uint8_t *src_data[4], const int src_linesizes[4], enum AVPixelFormat pix_fmt, int width, int height)
Copy image in src_data to dst_data.
AVCodecContext * codec
Codec context associated with this stream.
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)
int width
picture width / height.
attribute_deprecated uint8_t * data[AV_NUM_DATA_POINTERS]
pointers to the image data planes
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.
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
enum AVMediaType codec_type
virtual ULONG STDMETHODCALLTYPE AddRef(void)
int sample_rate
samples per second
int ff_decklink_list_devices(AVFormatContext *avctx)
main external API structure.
static const char * format
HRESULT ff_decklink_get_display_name(IDeckLink *This, const char **displayName)
BYTE int const BYTE int int int height
virtual BMDFrameFlags STDMETHODCALLTYPE GetFlags(void)
virtual HRESULT STDMETHODCALLTYPE GetBytes(void **buffer)
int av_frame_get_buffer(AVFrame *frame, int align)
Allocate new buffer(s) for audio or video data.
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
virtual HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted(IDeckLinkVideoFrame *_frame, BMDOutputFrameCompletionResult result)
virtual HRESULT STDMETHODCALLTYPE GetAncillaryData(IDeckLinkVideoFrameAncillary **ancillary)
virtual ULONG STDMETHODCALLTYPE AddRef(void)
int channels
number of audio channels
void * priv_data
Format private data.
int ff_decklink_write_packet(AVFormatContext *avctx, AVPacket *pkt)
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv)
virtual HRESULT STDMETHODCALLTYPE GetTimecode(BMDTimecodeFormat format, IDeckLinkTimecode **timecode)
AVPixelFormat
Pixel format.
This structure stores compressed data.
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
virtual ULONG STDMETHODCALLTYPE Release(void)