Commit | Line | Data |
---|---|---|
2ba45a60 DM |
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> | |
2ba45a60 DM |
23 | |
24 | #include <pthread.h> | |
25 | #include <semaphore.h> | |
26 | ||
27 | extern "C" { | |
28 | #include "libavformat/avformat.h" | |
29 | #include "libavformat/internal.h" | |
30 | #include "libavutil/imgutils.h" | |
31 | } | |
32 | ||
f6fa7814 | 33 | #include "decklink_common.h" |
2ba45a60 DM |
34 | #include "decklink_enc.h" |
35 | ||
2ba45a60 DM |
36 | |
37 | /* DeckLink callback class declaration */ | |
38 | class decklink_frame : public IDeckLinkVideoFrame | |
39 | { | |
40 | public: | |
41 | decklink_frame(struct decklink_ctx *ctx, AVFrame *avframe, long width, | |
42 | long height, void *buffer) : | |
43 | _ctx(ctx), _avframe(avframe), _width(width), | |
44 | _height(height), _buffer(buffer), _refs(0) { } | |
45 | ||
46 | virtual long STDMETHODCALLTYPE GetWidth (void) { return _width; } | |
47 | virtual long STDMETHODCALLTYPE GetHeight (void) { return _height; } | |
48 | virtual long STDMETHODCALLTYPE GetRowBytes (void) { return _width<<1; } | |
49 | virtual BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat(void) { return bmdFormat8BitYUV; } | |
50 | virtual BMDFrameFlags STDMETHODCALLTYPE GetFlags (void) { return bmdVideoOutputFlagDefault; } | |
51 | virtual HRESULT STDMETHODCALLTYPE GetBytes (void **buffer) { *buffer = _buffer; return S_OK; } | |
52 | ||
53 | virtual HRESULT STDMETHODCALLTYPE GetTimecode (BMDTimecodeFormat format, IDeckLinkTimecode **timecode) { return S_FALSE; } | |
54 | virtual HRESULT STDMETHODCALLTYPE GetAncillaryData(IDeckLinkVideoFrameAncillary **ancillary) { return S_FALSE; } | |
55 | ||
56 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv) { return E_NOINTERFACE; } | |
57 | virtual ULONG STDMETHODCALLTYPE AddRef(void) { return ++_refs; } | |
58 | virtual ULONG STDMETHODCALLTYPE Release(void) { if (!--_refs) delete this; return _refs; } | |
59 | ||
60 | struct decklink_ctx *_ctx; | |
61 | AVFrame *_avframe; | |
62 | ||
63 | private: | |
64 | long _width; | |
65 | long _height; | |
66 | void *_buffer; | |
67 | int _refs; | |
68 | }; | |
69 | ||
f6fa7814 | 70 | class decklink_output_callback : public IDeckLinkVideoOutputCallback |
2ba45a60 DM |
71 | { |
72 | public: | |
73 | virtual HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted(IDeckLinkVideoFrame *_frame, BMDOutputFrameCompletionResult result) | |
74 | { | |
75 | decklink_frame *frame = static_cast<decklink_frame *>(_frame); | |
76 | struct decklink_ctx *ctx = frame->_ctx; | |
77 | AVFrame *avframe = frame->_avframe; | |
78 | ||
79 | av_frame_free(&avframe); | |
80 | ||
81 | sem_post(&ctx->semaphore); | |
82 | ||
83 | return S_OK; | |
84 | } | |
85 | virtual HRESULT STDMETHODCALLTYPE ScheduledPlaybackHasStopped(void) { return S_OK; } | |
86 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv) { return E_NOINTERFACE; } | |
87 | virtual ULONG STDMETHODCALLTYPE AddRef(void) { return 1; } | |
88 | virtual ULONG STDMETHODCALLTYPE Release(void) { return 1; } | |
89 | }; | |
90 | ||
2ba45a60 DM |
91 | static int decklink_setup_video(AVFormatContext *avctx, AVStream *st) |
92 | { | |
93 | struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data; | |
94 | struct decklink_ctx *ctx = (struct decklink_ctx *) cctx->ctx; | |
95 | AVCodecContext *c = st->codec; | |
96 | ||
97 | if (ctx->video) { | |
98 | av_log(avctx, AV_LOG_ERROR, "Only one video stream is supported!\n"); | |
99 | return -1; | |
100 | } | |
101 | ||
102 | if (c->pix_fmt != AV_PIX_FMT_UYVY422) { | |
103 | av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format!" | |
104 | " Only AV_PIX_FMT_UYVY422 is supported.\n"); | |
105 | return -1; | |
106 | } | |
f6fa7814 | 107 | if (ff_decklink_set_format(avctx, c->width, c->height, |
2ba45a60 DM |
108 | c->time_base.num, c->time_base.den)) { |
109 | av_log(avctx, AV_LOG_ERROR, "Unsupported video size or framerate!" | |
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) { | |
115 | av_log(avctx, AV_LOG_ERROR, "Could not enable video output!\n"); | |
116 | return -1; | |
117 | } | |
118 | ||
119 | /* Set callback. */ | |
f6fa7814 DM |
120 | ctx->output_callback = new decklink_output_callback(); |
121 | ctx->dlo->SetScheduledFrameCompletionCallback(ctx->output_callback); | |
2ba45a60 DM |
122 | |
123 | /* Start video semaphore. */ | |
124 | ctx->frames_preroll = c->time_base.den * ctx->preroll; | |
125 | if (c->time_base.den > 1000) | |
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. */ | |
134 | avpriv_set_pts_info(st, 64, c->time_base.num, c->time_base.den); | |
135 | ||
136 | ctx->video = 1; | |
137 | ||
138 | return 0; | |
139 | } | |
140 | ||
141 | static int decklink_setup_audio(AVFormatContext *avctx, AVStream *st) | |
142 | { | |
143 | struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data; | |
144 | struct decklink_ctx *ctx = (struct decklink_ctx *) cctx->ctx; | |
145 | AVCodecContext *c = st->codec; | |
146 | ||
147 | if (ctx->audio) { | |
148 | av_log(avctx, AV_LOG_ERROR, "Only one audio stream is supported!\n"); | |
149 | return -1; | |
150 | } | |
151 | if (c->sample_rate != 48000) { | |
152 | av_log(avctx, AV_LOG_ERROR, "Unsupported sample rate!" | |
153 | " Only 48kHz is supported.\n"); | |
154 | return -1; | |
155 | } | |
156 | if (c->channels != 2 && c->channels != 8) { | |
157 | av_log(avctx, AV_LOG_ERROR, "Unsupported number of channels!" | |
158 | " Only stereo and 7.1 are supported.\n"); | |
159 | return -1; | |
160 | } | |
161 | if (ctx->dlo->EnableAudioOutput(bmdAudioSampleRate48kHz, | |
162 | bmdAudioSampleType16bitInteger, | |
163 | c->channels, | |
164 | bmdAudioOutputStreamTimestamped) != S_OK) { | |
165 | av_log(avctx, AV_LOG_ERROR, "Could not enable audio output!\n"); | |
166 | return -1; | |
167 | } | |
168 | if (ctx->dlo->BeginAudioPreroll() != S_OK) { | |
169 | av_log(avctx, AV_LOG_ERROR, "Could not begin audio preroll!\n"); | |
170 | return -1; | |
171 | } | |
172 | ||
173 | /* The device expects the sample rate to be fixed. */ | |
174 | avpriv_set_pts_info(st, 64, 1, c->sample_rate); | |
175 | ctx->channels = c->channels; | |
176 | ||
177 | ctx->audio = 1; | |
178 | ||
179 | return 0; | |
180 | } | |
181 | ||
182 | av_cold int ff_decklink_write_trailer(AVFormatContext *avctx) | |
183 | { | |
184 | struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data; | |
185 | struct decklink_ctx *ctx = (struct decklink_ctx *) cctx->ctx; | |
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(); | |
192 | if (ctx->audio) | |
193 | ctx->dlo->DisableAudioOutput(); | |
194 | } | |
195 | ||
196 | if (ctx->dlo) | |
197 | ctx->dlo->Release(); | |
198 | if (ctx->dl) | |
199 | ctx->dl->Release(); | |
200 | ||
f6fa7814 DM |
201 | if (ctx->output_callback) |
202 | delete ctx->output_callback; | |
2ba45a60 DM |
203 | |
204 | sem_destroy(&ctx->semaphore); | |
205 | ||
206 | av_freep(&cctx->ctx); | |
207 | ||
208 | return 0; | |
209 | } | |
210 | ||
211 | static int decklink_write_video_packet(AVFormatContext *avctx, AVPacket *pkt) | |
212 | { | |
213 | struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data; | |
214 | struct decklink_ctx *ctx = (struct decklink_ctx *) cctx->ctx; | |
215 | AVPicture *avpicture = (AVPicture *) pkt->data; | |
216 | AVFrame *avframe, *tmp; | |
217 | decklink_frame *frame; | |
218 | buffercount_type buffered; | |
219 | HRESULT hr; | |
220 | ||
221 | /* HACK while av_uncoded_frame() isn't implemented */ | |
222 | int ret; | |
223 | ||
224 | tmp = av_frame_alloc(); | |
225 | if (!tmp) | |
226 | return AVERROR(ENOMEM); | |
227 | tmp->format = AV_PIX_FMT_UYVY422; | |
228 | tmp->width = ctx->bmd_width; | |
229 | tmp->height = ctx->bmd_height; | |
230 | ret = av_frame_get_buffer(tmp, 32); | |
231 | if (ret < 0) { | |
232 | av_frame_free(&tmp); | |
233 | return ret; | |
234 | } | |
235 | av_image_copy(tmp->data, tmp->linesize, (const uint8_t **) avpicture->data, | |
236 | avpicture->linesize, (AVPixelFormat) tmp->format, tmp->width, | |
237 | tmp->height); | |
238 | avframe = av_frame_clone(tmp); | |
239 | av_frame_free(&tmp); | |
240 | if (!avframe) { | |
241 | av_log(avctx, AV_LOG_ERROR, "Could not clone video frame.\n"); | |
242 | return AVERROR(EIO); | |
243 | } | |
244 | /* end HACK */ | |
245 | ||
246 | frame = new decklink_frame(ctx, avframe, ctx->bmd_width, ctx->bmd_height, | |
247 | (void *) avframe->data[0]); | |
248 | if (!frame) { | |
249 | av_log(avctx, AV_LOG_ERROR, "Could not create new frame.\n"); | |
250 | return AVERROR(EIO); | |
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); | |
260 | if (hr != S_OK) { | |
261 | av_log(avctx, AV_LOG_ERROR, "Could not schedule video frame." | |
262 | " error %08x.\n", (uint32_t) hr); | |
263 | frame->Release(); | |
264 | return AVERROR(EIO); | |
265 | } | |
266 | ||
267 | ctx->dlo->GetBufferedVideoFrameCount(&buffered); | |
268 | av_log(avctx, AV_LOG_DEBUG, "Buffered video frames: %d.\n", (int) buffered); | |
269 | if (pkt->pts > 2 && buffered <= 2) | |
270 | av_log(avctx, AV_LOG_WARNING, "There are not enough buffered video frames." | |
271 | " Video may misbehave!\n"); | |
272 | ||
273 | /* Preroll video frames. */ | |
274 | if (!ctx->playback_started && pkt->pts > ctx->frames_preroll) { | |
275 | av_log(avctx, AV_LOG_DEBUG, "Ending audio preroll.\n"); | |
276 | if (ctx->audio && ctx->dlo->EndAudioPreroll() != S_OK) { | |
277 | av_log(avctx, AV_LOG_ERROR, "Could not end audio preroll!\n"); | |
278 | return AVERROR(EIO); | |
279 | } | |
280 | av_log(avctx, AV_LOG_DEBUG, "Starting scheduled playback.\n"); | |
281 | if (ctx->dlo->StartScheduledPlayback(0, ctx->bmd_tb_den, 1.0) != S_OK) { | |
282 | av_log(avctx, AV_LOG_ERROR, "Could not start scheduled playback!\n"); | |
283 | return AVERROR(EIO); | |
284 | } | |
285 | ctx->playback_started = 1; | |
286 | } | |
287 | ||
288 | return 0; | |
289 | } | |
290 | ||
291 | static int decklink_write_audio_packet(AVFormatContext *avctx, AVPacket *pkt) | |
292 | { | |
293 | struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data; | |
294 | struct decklink_ctx *ctx = (struct decklink_ctx *) cctx->ctx; | |
295 | int sample_count = pkt->size / (ctx->channels << 1); | |
296 | buffercount_type buffered; | |
297 | ||
298 | ctx->dlo->GetBufferedAudioSampleFrameCount(&buffered); | |
299 | if (pkt->pts > 1 && !buffered) | |
300 | av_log(avctx, AV_LOG_WARNING, "There's no buffered audio." | |
301 | " Audio will misbehave!\n"); | |
302 | ||
303 | if (ctx->dlo->ScheduleAudioSamples(pkt->data, sample_count, pkt->pts, | |
304 | bmdAudioSampleRate48kHz, NULL) != S_OK) { | |
305 | av_log(avctx, AV_LOG_ERROR, "Could not schedule audio samples.\n"); | |
306 | return AVERROR(EIO); | |
307 | } | |
308 | ||
309 | return 0; | |
310 | } | |
311 | ||
312 | extern "C" { | |
313 | ||
314 | av_cold int ff_decklink_write_header(AVFormatContext *avctx) | |
315 | { | |
316 | struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data; | |
317 | struct decklink_ctx *ctx; | |
f6fa7814 | 318 | IDeckLinkDisplayModeIterator *itermode; |
2ba45a60 DM |
319 | IDeckLinkIterator *iter; |
320 | IDeckLink *dl = NULL; | |
321 | unsigned int n; | |
322 | ||
323 | ctx = (struct decklink_ctx *) av_mallocz(sizeof(struct decklink_ctx)); | |
324 | if (!ctx) | |
325 | return AVERROR(ENOMEM); | |
326 | ctx->list_devices = cctx->list_devices; | |
327 | ctx->list_formats = cctx->list_formats; | |
328 | ctx->preroll = cctx->preroll; | |
329 | cctx->ctx = ctx; | |
330 | ||
331 | iter = CreateDeckLinkIteratorInstance(); | |
332 | if (!iter) { | |
333 | av_log(avctx, AV_LOG_ERROR, "Could not create DeckLink iterator\n"); | |
334 | return AVERROR(EIO); | |
335 | } | |
336 | ||
337 | /* List available devices. */ | |
338 | if (ctx->list_devices) { | |
f6fa7814 | 339 | ff_decklink_list_devices(avctx); |
2ba45a60 DM |
340 | return AVERROR_EXIT; |
341 | } | |
342 | ||
343 | /* Open device. */ | |
344 | while (iter->Next(&dl) == S_OK) { | |
345 | const char *displayName; | |
f6fa7814 | 346 | ff_decklink_get_display_name(dl, &displayName); |
2ba45a60 DM |
347 | if (!strcmp(avctx->filename, displayName)) { |
348 | av_free((void *) displayName); | |
349 | ctx->dl = dl; | |
350 | break; | |
351 | } | |
352 | av_free((void *) displayName); | |
353 | dl->Release(); | |
354 | } | |
355 | iter->Release(); | |
356 | if (!ctx->dl) { | |
357 | av_log(avctx, AV_LOG_ERROR, "Could not open '%s'\n", avctx->filename); | |
358 | return AVERROR(EIO); | |
359 | } | |
360 | ||
361 | /* Get output device. */ | |
362 | if (ctx->dl->QueryInterface(IID_IDeckLinkOutput, (void **) &ctx->dlo) != S_OK) { | |
363 | av_log(avctx, AV_LOG_ERROR, "Could not open output device from '%s'\n", | |
364 | avctx->filename); | |
365 | ctx->dl->Release(); | |
366 | return AVERROR(EIO); | |
367 | } | |
368 | ||
2ba45a60 DM |
369 | /* List supported formats. */ |
370 | if (ctx->list_formats) { | |
f6fa7814 | 371 | ff_decklink_list_formats(avctx); |
2ba45a60 DM |
372 | ctx->dlo->Release(); |
373 | ctx->dl->Release(); | |
374 | return AVERROR_EXIT; | |
375 | } | |
376 | ||
f6fa7814 DM |
377 | if (ctx->dlo->GetDisplayModeIterator(&itermode) != S_OK) { |
378 | av_log(avctx, AV_LOG_ERROR, "Could not get Display Mode Iterator\n"); | |
379 | ctx->dl->Release(); | |
380 | return AVERROR(EIO); | |
381 | } | |
382 | ||
2ba45a60 DM |
383 | /* Setup streams. */ |
384 | for (n = 0; n < avctx->nb_streams; n++) { | |
385 | AVStream *st = avctx->streams[n]; | |
386 | AVCodecContext *c = st->codec; | |
387 | if (c->codec_type == AVMEDIA_TYPE_AUDIO) { | |
388 | if (decklink_setup_audio(avctx, st)) | |
389 | goto error; | |
390 | } else if (c->codec_type == AVMEDIA_TYPE_VIDEO) { | |
391 | if (decklink_setup_video(avctx, st)) | |
392 | goto error; | |
393 | } else { | |
394 | av_log(avctx, AV_LOG_ERROR, "Unsupported stream type.\n"); | |
395 | goto error; | |
396 | } | |
397 | } | |
f6fa7814 | 398 | itermode->Release(); |
2ba45a60 DM |
399 | |
400 | return 0; | |
401 | ||
402 | error: | |
403 | ||
404 | ctx->dlo->Release(); | |
405 | ctx->dl->Release(); | |
406 | ||
407 | return AVERROR(EIO); | |
408 | } | |
409 | ||
410 | int ff_decklink_write_packet(AVFormatContext *avctx, AVPacket *pkt) | |
411 | { | |
412 | struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data; | |
413 | struct decklink_ctx *ctx = (struct decklink_ctx *) cctx->ctx; | |
414 | AVStream *st = avctx->streams[pkt->stream_index]; | |
415 | ||
416 | ctx->last_pts = FFMAX(ctx->last_pts, pkt->pts); | |
417 | ||
418 | if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) | |
419 | return decklink_write_video_packet(avctx, pkt); | |
420 | else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) | |
421 | return decklink_write_audio_packet(avctx, pkt); | |
422 | ||
423 | return AVERROR(EIO); | |
424 | } | |
425 | ||
426 | } /* extern "C" */ |