libav_utils.cpp 4.07 KB
Newer Older
1
/*
2
 *  Copyright (C) 2004-2017 Savoir-faire Linux Inc.
Guillaume Roguez's avatar
Guillaume Roguez committed
3
 *
4
 *  Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com>
5
 *  Author: Luca Barbato <lu_zero@gentoo.org>
6
 *  Author: Guillaume Roguez <Guillaume.Roguez@savoirfairelinux.com>
7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
20
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
21 22
 */

23 24
#include "libav_deps.h" // MUST BE INCLUDED FIRST

Alexandre Lision's avatar
Alexandre Lision committed
25
#include "config.h"
26
#include "video/video_base.h"
27 28
#include "logger.h"

29
#include <vector>
30 31 32
#include <algorithm>
#include <string>
#include <iostream>
33 34 35
#include <thread>
#include <mutex>
#include <exception>
36
#include <ciso646> // fix windows compiler bug
37

Guillaume Roguez's avatar
Guillaume Roguez committed
38 39
namespace ring { namespace libav_utils {

40
// protect libav/ffmpeg access
41 42
static int
avcodecManageMutex(void **data, enum AVLockOp op)
43
{
44
    auto mutex = reinterpret_cast<std::mutex**>(data);
45 46
    int ret = 0;
    switch (op) {
Tristan Matthews's avatar
Tristan Matthews committed
47
        case AV_LOCK_CREATE:
48 49 50
            try {
                *mutex = new std::mutex;
            } catch (const std::bad_alloc& e) {
51
                return AVERROR(ENOMEM);
52
            }
53
            break;
Tristan Matthews's avatar
Tristan Matthews committed
54
        case AV_LOCK_OBTAIN:
55
            (*mutex)->lock();
Tristan Matthews's avatar
Tristan Matthews committed
56 57
            break;
        case AV_LOCK_RELEASE:
58
            (*mutex)->unlock();
Tristan Matthews's avatar
Tristan Matthews committed
59
            break;
60
        case AV_LOCK_DESTROY:
61 62
            delete *mutex;
            *mutex = nullptr;
63 64
            break;
        default:
65
#ifdef AVERROR_BUG
66
            return AVERROR_BUG;
67 68
#else
            break;
69
#endif
70
    }
71
    return AVERROR(ret);
72 73
}

74
static constexpr const char* AVLOGLEVEL = "AVLOGLEVEL";
75

76 77 78
static void
setAvLogLevel()
{
79
#ifndef RING_UWP
80
    char* envvar = getenv(AVLOGLEVEL);
81
    signed level = AV_LOG_WARNING;
82 83 84 85 86 87 88 89

    if (envvar != nullptr) {
        if (not (std::istringstream(envvar) >> level))
            level = AV_LOG_ERROR;

        level = std::max(AV_LOG_QUIET, std::min(level, AV_LOG_DEBUG));
    }
    av_log_set_level(level);
90 91 92
#else
    av_log_set_level(0);
#endif
93 94 95 96
}

static void
init_once()
97
{
98
    av_register_all();
99
    avdevice_register_all();
100
    avformat_network_init();
101

102
    av_lockmgr_register(avcodecManageMutex);
103

Vittorio Giovara's avatar
Vittorio Giovara committed
104
    if (getDebugMode())
105
        setAvLogLevel();
106 107
}

108
static std::once_flag already_called;
109

110
void ring_avcodec_init()
111
{
112
    std::call_once(already_called, init_once);
113 114
}

115

116 117 118
int libav_pixel_format(int fmt)
{
    switch (fmt) {
119
        case video::VIDEO_PIXFMT_BGRA: return PIXEL_FORMAT(BGRA);
120
        case video::VIDEO_PIXFMT_RGBA: return PIXEL_FORMAT(RGBA);
121
        case video::VIDEO_PIXFMT_YUYV422: return PIXEL_FORMAT(YUYV422);
122 123
        case video::VIDEO_PIXFMT_YUV420P: return PIXEL_FORMAT(YUV420P);
        case video::VIDEO_PIXFMT_NV21: return PIXEL_FORMAT(NV21);
124 125 126 127
    }
    return fmt;
}

128
int ring_pixel_format(int fmt)
129 130
{
    switch (fmt) {
131
        case PIXEL_FORMAT(YUYV422): return video::VIDEO_PIXFMT_YUYV422;
132 133 134 135
    }
    return fmt;
}

136
void ring_url_split(const char *url,
137 138 139 140 141 142 143
                   char *hostname, size_t hostname_size, int *port,
                   char *path, size_t path_size)
{
    av_url_split(NULL, 0, NULL, 0, hostname, hostname_size, port,
                 path, path_size, url);
}

144 145 146 147 148 149 150 151 152 153 154 155 156 157
bool
is_yuv_planar(const AVPixFmtDescriptor& desc)
{
    if (not (desc.flags & AV_PIX_FMT_FLAG_PLANAR) or desc.flags & AV_PIX_FMT_FLAG_RGB)
        return false;

    /* handle formats that do not use all planes */
    unsigned used_bit_mask = (1u << desc.nb_components) - 1;
    for (unsigned i = 0; i < desc.nb_components; ++i)
        used_bit_mask &= ~(1u << desc.comp[i].plane);

    return not used_bit_mask;
}

Guillaume Roguez's avatar
Guillaume Roguez committed
158
}} // namespace ring::libav_utils