Browse code

avdevice/decklink_enc: convert AVFMT_RAWPICTURE to AV_CODEC_ID_WRAPPED_AVFRAME

Signed-off-by: Marton Balint <cus@passwd.hu>

Marton Balint authored on 2017/02/18 11:13:56
Showing 3 changed files
... ...
@@ -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, \