GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/vp9_metadata_bsf.c Lines: 33 51 64.7 %
Date: 2020-08-13 15:06:06 Branches: 15 42 35.7 %

Line Branch Exec Source
1
/*
2
 * This file is part of FFmpeg.
3
 *
4
 * FFmpeg is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
6
 * License as published by the Free Software Foundation; either
7
 * version 2.1 of the License, or (at your option) any later version.
8
 *
9
 * FFmpeg is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 * Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15
 * License along with FFmpeg; if not, write to the Free Software
16
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
 */
18
19
#include "libavutil/avstring.h"
20
#include "libavutil/common.h"
21
#include "libavutil/opt.h"
22
23
#include "bsf.h"
24
#include "bsf_internal.h"
25
#include "cbs.h"
26
#include "cbs_vp9.h"
27
28
typedef struct VP9MetadataContext {
29
    const AVClass *class;
30
31
    CodedBitstreamContext *cbc;
32
    CodedBitstreamFragment fragment;
33
34
    int color_space;
35
    int color_range;
36
37
    int color_warnings;
38
} VP9MetadataContext;
39
40
41
366
static int vp9_metadata_filter(AVBSFContext *bsf, AVPacket *pkt)
42
{
43
366
    VP9MetadataContext *ctx = bsf->priv_data;
44
366
    CodedBitstreamFragment *frag = &ctx->fragment;
45
    int err, i;
46
47
366
    err = ff_bsf_get_packet_ref(bsf, pkt);
48
366
    if (err < 0)
49
183
        return err;
50
51
183
    err = ff_cbs_read_packet(ctx->cbc, frag, pkt);
52
183
    if (err < 0) {
53
        av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n");
54
        goto fail;
55
    }
56
57
380
    for (i = 0; i < frag->nb_units; i++) {
58
197
        VP9RawFrame *frame = frag->units[i].content;
59
197
        VP9RawFrameHeader *header = &frame->header;
60
197
        int profile = (header->profile_high_bit << 1) + header->profile_low_bit;
61
62
197
        if (header->frame_type == VP9_KEY_FRAME ||
63

167
            header->intra_only && profile > 0) {
64
30
            if (ctx->color_space >= 0) {
65
                if (!(profile & 1) && ctx->color_space == VP9_CS_RGB) {
66
                    if (!(ctx->color_warnings & 2)) {
67
                        av_log(bsf, AV_LOG_WARNING, "Warning: RGB "
68
                               "incompatible with profiles 0 and 2.\n");
69
                        ctx->color_warnings |= 2;
70
                    }
71
                } else
72
                    header->color_space = ctx->color_space;
73
            }
74
75
30
            if (ctx->color_range >= 0)
76
                header->color_range = ctx->color_range;
77
30
            if (header->color_space == VP9_CS_RGB) {
78
                if (!(ctx->color_warnings & 1) && !header->color_range) {
79
                    av_log(bsf, AV_LOG_WARNING, "Warning: Color space RGB "
80
                           "implicitly sets color range to PC range.\n");
81
                    ctx->color_warnings |= 1;
82
                }
83
                header->color_range = 1;
84
            }
85

167
        } else if (!(ctx->color_warnings & 4) && header->intra_only && !profile &&
86
                   ctx->color_space >= 0 && ctx->color_space != VP9_CS_BT_601) {
87
            av_log(bsf, AV_LOG_WARNING, "Warning: Intra-only frames in "
88
                   "profile 0 are automatically BT.601.\n");
89
            ctx->color_warnings |= 4;
90
        }
91
    }
92
93
183
    err = ff_cbs_write_packet(ctx->cbc, pkt, frag);
94
183
    if (err < 0) {
95
        av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n");
96
        goto fail;
97
    }
98
99
183
    err = 0;
100
183
fail:
101
183
    ff_cbs_fragment_reset(frag);
102
103
183
    if (err < 0)
104
        av_packet_unref(pkt);
105
106
183
    return err;
107
}
108
109
14
static int vp9_metadata_init(AVBSFContext *bsf)
110
{
111
14
    VP9MetadataContext *ctx = bsf->priv_data;
112
113
14
    return ff_cbs_init(&ctx->cbc, AV_CODEC_ID_VP9, bsf);
114
}
115
116
14
static void vp9_metadata_close(AVBSFContext *bsf)
117
{
118
14
    VP9MetadataContext *ctx = bsf->priv_data;
119
120
14
    ff_cbs_fragment_free(&ctx->fragment);
121
14
    ff_cbs_close(&ctx->cbc);
122
14
}
123
124
#define OFFSET(x) offsetof(VP9MetadataContext, x)
125
#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM)
126
static const AVOption vp9_metadata_options[] = {
127
    { "color_space", "Set colour space (section 7.2.2)",
128
        OFFSET(color_space), AV_OPT_TYPE_INT,
129
        { .i64 = -1 }, -1, VP9_CS_RGB, FLAGS, "cs" },
130
    { "unknown",  "Unknown/unspecified",  0, AV_OPT_TYPE_CONST,
131
        { .i64 = VP9_CS_UNKNOWN   }, .flags = FLAGS, .unit = "cs" },
132
    { "bt601",    "ITU-R BT.601-7",       0, AV_OPT_TYPE_CONST,
133
        { .i64 = VP9_CS_BT_601    }, .flags = FLAGS, .unit = "cs" },
134
    { "bt709",    "ITU-R BT.709-6",       0, AV_OPT_TYPE_CONST,
135
        { .i64 = VP9_CS_BT_709    }, .flags = FLAGS, .unit = "cs" },
136
    { "smpte170", "SMPTE-170",            0, AV_OPT_TYPE_CONST,
137
        { .i64 = VP9_CS_SMPTE_170 }, .flags = FLAGS, .unit = "cs" },
138
    { "smpte240", "SMPTE-240",            0, AV_OPT_TYPE_CONST,
139
        { .i64 = VP9_CS_SMPTE_240 }, .flags = FLAGS, .unit = "cs" },
140
    { "bt2020",   "ITU-R BT.2020-2",      0, AV_OPT_TYPE_CONST,
141
        { .i64 = VP9_CS_BT_2020   }, .flags = FLAGS, .unit = "cs" },
142
    { "rgb",      "sRGB / IEC 61966-2-1", 0, AV_OPT_TYPE_CONST,
143
        { .i64 = VP9_CS_RGB       }, .flags = FLAGS, .unit = "cs" },
144
145
    { "color_range", "Set colour range (section 7.2.2)",
146
        OFFSET(color_range), AV_OPT_TYPE_INT,
147
        { .i64 = -1 }, -1, 1, FLAGS, "cr" },
148
    { "tv", "TV (limited) range", 0, AV_OPT_TYPE_CONST,
149
        { .i64 = 0 }, .flags = FLAGS, .unit = "cr" },
150
    { "pc", "PC (full) range",    0, AV_OPT_TYPE_CONST,
151
        { .i64 = 1 }, .flags = FLAGS, .unit = "cr" },
152
153
    { NULL }
154
};
155
156
static const AVClass vp9_metadata_class = {
157
    .class_name = "vp9_metadata_bsf",
158
    .item_name  = av_default_item_name,
159
    .option     = vp9_metadata_options,
160
    .version    = LIBAVUTIL_VERSION_INT,
161
};
162
163
static const enum AVCodecID vp9_metadata_codec_ids[] = {
164
    AV_CODEC_ID_VP9, AV_CODEC_ID_NONE,
165
};
166
167
const AVBitStreamFilter ff_vp9_metadata_bsf = {
168
    .name           = "vp9_metadata",
169
    .priv_data_size = sizeof(VP9MetadataContext),
170
    .priv_class     = &vp9_metadata_class,
171
    .init           = &vp9_metadata_init,
172
    .close          = &vp9_metadata_close,
173
    .filter         = &vp9_metadata_filter,
174
    .codec_ids      = vp9_metadata_codec_ids,
175
};