Signed-off-by: Marton Balint <cus@passwd.hu>
Marton Balint authored on 2017/02/18 11:13:56... | ... |
@@ -28,6 +28,7 @@ extern "C" { |
28 | 28 |
#include "libavformat/avformat.h" |
29 | 29 |
#include "libavformat/internal.h" |
30 | 30 |
#include "libavutil/imgutils.h" |
31 |
+#include "libavutil/atomic.h" |
|
31 | 32 |
} |
32 | 33 |
|
33 | 34 |
#include "decklink_common.h" |
... | ... |
@@ -38,33 +39,43 @@ extern "C" { |
38 | 38 |
class decklink_frame : public IDeckLinkVideoFrame |
39 | 39 |
{ |
40 | 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; } |
|
41 |
+ decklink_frame(struct decklink_ctx *ctx, AVFrame *avframe) : |
|
42 |
+ _ctx(ctx), _avframe(avframe), _refs(1) { } |
|
43 |
+ |
|
44 |
+ virtual long STDMETHODCALLTYPE GetWidth (void) { return _avframe->width; } |
|
45 |
+ virtual long STDMETHODCALLTYPE GetHeight (void) { return _avframe->height; } |
|
46 |
+ virtual long STDMETHODCALLTYPE GetRowBytes (void) { return _avframe->linesize[0] < 0 ? -_avframe->linesize[0] : _avframe->linesize[0]; } |
|
49 | 47 |
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; } |
|
48 |
+ virtual BMDFrameFlags STDMETHODCALLTYPE GetFlags (void) { return _avframe->linesize[0] < 0 ? bmdFrameFlagFlipVertical : bmdFrameFlagDefault; } |
|
49 |
+ virtual HRESULT STDMETHODCALLTYPE GetBytes (void **buffer) |
|
50 |
+ { |
|
51 |
+ if (_avframe->linesize[0] < 0) |
|
52 |
+ *buffer = (void *)(_avframe->data[0] + _avframe->linesize[0] * (_avframe->height - 1)); |
|
53 |
+ else |
|
54 |
+ *buffer = (void *)(_avframe->data[0]); |
|
55 |
+ return S_OK; |
|
56 |
+ } |
|
52 | 57 |
|
53 | 58 |
virtual HRESULT STDMETHODCALLTYPE GetTimecode (BMDTimecodeFormat format, IDeckLinkTimecode **timecode) { return S_FALSE; } |
54 | 59 |
virtual HRESULT STDMETHODCALLTYPE GetAncillaryData(IDeckLinkVideoFrameAncillary **ancillary) { return S_FALSE; } |
55 | 60 |
|
56 | 61 |
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 0;} return _refs; } |
|
62 |
+ virtual ULONG STDMETHODCALLTYPE AddRef(void) { return avpriv_atomic_int_add_and_fetch(&_refs, 1); } |
|
63 |
+ virtual ULONG STDMETHODCALLTYPE Release(void) |
|
64 |
+ { |
|
65 |
+ int ret = avpriv_atomic_int_add_and_fetch(&_refs, -1); |
|
66 |
+ if (!ret) { |
|
67 |
+ av_frame_free(&_avframe); |
|
68 |
+ delete this; |
|
69 |
+ } |
|
70 |
+ return ret; |
|
71 |
+ } |
|
59 | 72 |
|
60 | 73 |
struct decklink_ctx *_ctx; |
61 | 74 |
AVFrame *_avframe; |
62 | 75 |
|
63 | 76 |
private: |
64 |
- long _width; |
|
65 |
- long _height; |
|
66 |
- void *_buffer; |
|
67 |
- int _refs; |
|
77 |
+ volatile int _refs; |
|
68 | 78 |
}; |
69 | 79 |
|
70 | 80 |
class decklink_output_callback : public IDeckLinkVideoOutputCallback |
... | ... |
@@ -76,7 +87,7 @@ public: |
76 | 76 |
struct decklink_ctx *ctx = frame->_ctx; |
77 | 77 |
AVFrame *avframe = frame->_avframe; |
78 | 78 |
|
79 |
- av_frame_free(&avframe); |
|
79 |
+ av_frame_unref(avframe); |
|
80 | 80 |
|
81 | 81 |
sem_post(&ctx->semaphore); |
82 | 82 |
|
... | ... |
@@ -209,41 +220,27 @@ static int decklink_write_video_packet(AVFormatContext *avctx, AVPacket *pkt) |
209 | 209 |
{ |
210 | 210 |
struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; |
211 | 211 |
struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx; |
212 |
- AVPicture *avpicture = (AVPicture *) pkt->data; |
|
213 |
- AVFrame *avframe, *tmp; |
|
212 |
+ AVFrame *avframe, *tmp = (AVFrame *)pkt->data; |
|
214 | 213 |
decklink_frame *frame; |
215 | 214 |
buffercount_type buffered; |
216 | 215 |
HRESULT hr; |
217 | 216 |
|
218 |
- /* HACK while av_uncoded_frame() isn't implemented */ |
|
219 |
- int ret; |
|
220 |
- |
|
221 |
- tmp = av_frame_alloc(); |
|
222 |
- if (!tmp) |
|
223 |
- return AVERROR(ENOMEM); |
|
224 |
- tmp->format = AV_PIX_FMT_UYVY422; |
|
225 |
- tmp->width = ctx->bmd_width; |
|
226 |
- tmp->height = ctx->bmd_height; |
|
227 |
- ret = av_frame_get_buffer(tmp, 32); |
|
228 |
- if (ret < 0) { |
|
229 |
- av_frame_free(&tmp); |
|
230 |
- return ret; |
|
217 |
+ if (tmp->format != AV_PIX_FMT_UYVY422 || |
|
218 |
+ tmp->width != ctx->bmd_width || |
|
219 |
+ tmp->height != ctx->bmd_height) { |
|
220 |
+ av_log(avctx, AV_LOG_ERROR, "Got a frame with invalid pixel format or dimension.\n"); |
|
221 |
+ return AVERROR(EINVAL); |
|
231 | 222 |
} |
232 |
- av_image_copy(tmp->data, tmp->linesize, (const uint8_t **) avpicture->data, |
|
233 |
- avpicture->linesize, (AVPixelFormat) tmp->format, tmp->width, |
|
234 |
- tmp->height); |
|
235 | 223 |
avframe = av_frame_clone(tmp); |
236 |
- av_frame_free(&tmp); |
|
237 | 224 |
if (!avframe) { |
238 | 225 |
av_log(avctx, AV_LOG_ERROR, "Could not clone video frame.\n"); |
239 | 226 |
return AVERROR(EIO); |
240 | 227 |
} |
241 |
- /* end HACK */ |
|
242 | 228 |
|
243 |
- frame = new decklink_frame(ctx, avframe, ctx->bmd_width, ctx->bmd_height, |
|
244 |
- (void *) avframe->data[0]); |
|
229 |
+ frame = new decklink_frame(ctx, avframe); |
|
245 | 230 |
if (!frame) { |
246 | 231 |
av_log(avctx, AV_LOG_ERROR, "Could not create new frame.\n"); |
232 |
+ av_frame_free(&avframe); |
|
247 | 233 |
return AVERROR(EIO); |
248 | 234 |
} |
249 | 235 |
|
... | ... |
@@ -254,10 +251,11 @@ static int decklink_write_video_packet(AVFormatContext *avctx, AVPacket *pkt) |
254 | 254 |
hr = ctx->dlo->ScheduleVideoFrame((struct IDeckLinkVideoFrame *) frame, |
255 | 255 |
pkt->pts * ctx->bmd_tb_num, |
256 | 256 |
ctx->bmd_tb_num, ctx->bmd_tb_den); |
257 |
+ /* Pass ownership to DeckLink, or release on failure */ |
|
258 |
+ frame->Release(); |
|
257 | 259 |
if (hr != S_OK) { |
258 | 260 |
av_log(avctx, AV_LOG_ERROR, "Could not schedule video frame." |
259 | 261 |
" error %08x.\n", (uint32_t) hr); |
260 |
- frame->Release(); |
|
261 | 262 |
return AVERROR(EIO); |
262 | 263 |
} |
263 | 264 |
|
... | ... |
@@ -46,9 +46,9 @@ AVOutputFormat ff_decklink_muxer = { |
46 | 46 |
.name = "decklink", |
47 | 47 |
.long_name = NULL_IF_CONFIG_SMALL("Blackmagic DeckLink output"), |
48 | 48 |
.audio_codec = AV_CODEC_ID_PCM_S16LE, |
49 |
- .video_codec = AV_CODEC_ID_RAWVIDEO, |
|
49 |
+ .video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, |
|
50 | 50 |
.subtitle_codec = AV_CODEC_ID_NONE, |
51 |
- .flags = AVFMT_NOFILE | AVFMT_RAWPICTURE, |
|
51 |
+ .flags = AVFMT_NOFILE, |
|
52 | 52 |
.priv_class = &decklink_muxer_class, |
53 | 53 |
.priv_data_size = sizeof(struct decklink_cctx), |
54 | 54 |
.write_header = ff_decklink_write_header, |
... | ... |
@@ -28,8 +28,8 @@ |
28 | 28 |
#include "libavutil/version.h" |
29 | 29 |
|
30 | 30 |
#define LIBAVDEVICE_VERSION_MAJOR 57 |
31 |
-#define LIBAVDEVICE_VERSION_MINOR 2 |
|
32 |
-#define LIBAVDEVICE_VERSION_MICRO 101 |
|
31 |
+#define LIBAVDEVICE_VERSION_MINOR 3 |
|
32 |
+#define LIBAVDEVICE_VERSION_MICRO 100 |
|
33 | 33 |
|
34 | 34 |
#define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ |
35 | 35 |
LIBAVDEVICE_VERSION_MINOR, \ |