GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/h264_redundant_pps_bsf.c Lines: 0 82 0.0 %
Date: 2019-11-22 03:34:36 Branches: 0 38 0.0 %

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 <string.h>
20
21
#include "libavutil/common.h"
22
#include "libavutil/mem.h"
23
24
#include "bsf.h"
25
#include "cbs.h"
26
#include "cbs_h264.h"
27
#include "h264.h"
28
29
30
typedef struct H264RedundantPPSContext {
31
    CodedBitstreamContext *input;
32
    CodedBitstreamContext *output;
33
34
    CodedBitstreamFragment access_unit;
35
36
    int global_pic_init_qp;
37
    int current_pic_init_qp;
38
    int extradata_pic_init_qp;
39
} H264RedundantPPSContext;
40
41
42
static int h264_redundant_pps_fixup_pps(H264RedundantPPSContext *ctx,
43
                                        H264RawPPS *pps)
44
{
45
    // Record the current value of pic_init_qp in order to fix up
46
    // following slices, then overwrite with the global value.
47
    ctx->current_pic_init_qp = pps->pic_init_qp_minus26 + 26;
48
    pps->pic_init_qp_minus26 = ctx->global_pic_init_qp - 26;
49
50
    // Some PPSs have this set, so it must be set in all of them.
51
    // (Slices which do not use such a PPS on input will still have
52
    // *_weight_l*flag as zero and therefore write equivalently.)
53
    pps->weighted_pred_flag = 1;
54
55
    return 0;
56
}
57
58
static int h264_redundant_pps_fixup_slice(H264RedundantPPSContext *ctx,
59
                                          H264RawSliceHeader *slice)
60
{
61
    int qp;
62
63
    qp = ctx->current_pic_init_qp + slice->slice_qp_delta;
64
    slice->slice_qp_delta = qp - ctx->global_pic_init_qp;
65
66
    return 0;
67
}
68
69
static int h264_redundant_pps_filter(AVBSFContext *bsf, AVPacket *pkt)
70
{
71
    H264RedundantPPSContext *ctx = bsf->priv_data;
72
    CodedBitstreamFragment *au = &ctx->access_unit;
73
    int au_has_sps;
74
    int err, i;
75
76
    err = ff_bsf_get_packet_ref(bsf, pkt);
77
    if (err < 0)
78
        return err;
79
80
    err = ff_cbs_read_packet(ctx->input, au, pkt);
81
    if (err < 0)
82
        goto fail;
83
84
    au_has_sps = 0;
85
    for (i = 0; i < au->nb_units; i++) {
86
        CodedBitstreamUnit *nal = &au->units[i];
87
88
        if (nal->type == H264_NAL_SPS)
89
            au_has_sps = 1;
90
        if (nal->type == H264_NAL_PPS) {
91
            err = h264_redundant_pps_fixup_pps(ctx, nal->content);
92
            if (err < 0)
93
                goto fail;
94
            if (!au_has_sps) {
95
                av_log(bsf, AV_LOG_VERBOSE, "Deleting redundant PPS "
96
                       "at %"PRId64".\n", pkt->pts);
97
                ff_cbs_delete_unit(ctx->input, au, i);
98
                i--;
99
                continue;
100
            }
101
        }
102
        if (nal->type == H264_NAL_SLICE ||
103
            nal->type == H264_NAL_IDR_SLICE) {
104
            H264RawSlice *slice = nal->content;
105
            h264_redundant_pps_fixup_slice(ctx, &slice->header);
106
        }
107
    }
108
109
    err = ff_cbs_write_packet(ctx->output, pkt, au);
110
    if (err < 0)
111
        goto fail;
112
113
    err = 0;
114
fail:
115
    ff_cbs_fragment_reset(ctx->output, au);
116
    if (err < 0)
117
        av_packet_unref(pkt);
118
119
    return err;
120
}
121
122
static int h264_redundant_pps_init(AVBSFContext *bsf)
123
{
124
    H264RedundantPPSContext *ctx = bsf->priv_data;
125
    CodedBitstreamFragment *au = &ctx->access_unit;
126
    int err, i;
127
128
    err = ff_cbs_init(&ctx->input, AV_CODEC_ID_H264, bsf);
129
    if (err < 0)
130
        return err;
131
132
    err = ff_cbs_init(&ctx->output, AV_CODEC_ID_H264, bsf);
133
    if (err < 0)
134
        return err;
135
136
    ctx->global_pic_init_qp = 26;
137
138
    if (bsf->par_in->extradata) {
139
        err = ff_cbs_read_extradata(ctx->input, au, bsf->par_in);
140
        if (err < 0) {
141
            av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n");
142
            goto fail;
143
        }
144
145
        for (i = 0; i < au->nb_units; i++) {
146
            if (au->units[i].type == H264_NAL_PPS) {
147
                err = h264_redundant_pps_fixup_pps(ctx, au->units[i].content);
148
                if (err < 0)
149
                    goto fail;
150
            }
151
        }
152
153
        ctx->extradata_pic_init_qp = ctx->current_pic_init_qp;
154
        err = ff_cbs_write_extradata(ctx->output, bsf->par_out, au);
155
        if (err < 0) {
156
            av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n");
157
            goto fail;
158
        }
159
    }
160
161
    err = 0;
162
fail:
163
    ff_cbs_fragment_reset(ctx->output, au);
164
    return err;
165
}
166
167
static void h264_redundant_pps_flush(AVBSFContext *bsf)
168
{
169
    H264RedundantPPSContext *ctx = bsf->priv_data;
170
    ctx->current_pic_init_qp = ctx->extradata_pic_init_qp;
171
}
172
173
static void h264_redundant_pps_close(AVBSFContext *bsf)
174
{
175
    H264RedundantPPSContext *ctx = bsf->priv_data;
176
177
    ff_cbs_fragment_free(ctx->input, &ctx->access_unit);
178
    ff_cbs_close(&ctx->input);
179
    ff_cbs_close(&ctx->output);
180
}
181
182
static const enum AVCodecID h264_redundant_pps_codec_ids[] = {
183
    AV_CODEC_ID_H264, AV_CODEC_ID_NONE,
184
};
185
186
const AVBitStreamFilter ff_h264_redundant_pps_bsf = {
187
    .name           = "h264_redundant_pps",
188
    .priv_data_size = sizeof(H264RedundantPPSContext),
189
    .init           = &h264_redundant_pps_init,
190
    .flush          = &h264_redundant_pps_flush,
191
    .close          = &h264_redundant_pps_close,
192
    .filter         = &h264_redundant_pps_filter,
193
    .codec_ids      = h264_redundant_pps_codec_ids,
194
};