~ubuntu-branches/ubuntu/trusty/gst-libav1.0/trusty-proposed

« back to all changes in this revision

Viewing changes to gst-libs/ext/libav/libavcodec/libxavs.c

  • Committer: Package Import Robot
  • Author(s): Sebastian Dröge
  • Date: 2013-09-24 17:07:00 UTC
  • mfrom: (1.1.17) (7.1.9 experimental)
  • Revision ID: package-import@ubuntu.com-20130924170700-4dg62s3pwl0pdakz
Tags: 1.2.0-1
* New upstream stable release:
  + debian/control:
    - Build depend on GStreamer and gst-plugins-base >= 1.2.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
#include <xavs.h>
29
29
#include "avcodec.h"
30
30
#include "internal.h"
 
31
#include "libavutil/internal.h"
 
32
#include "libavutil/mem.h"
31
33
#include "libavutil/opt.h"
32
34
 
33
35
#define END_OF_STREAM 0x001
37
39
#define XAVS_PART_B8X8 0x100 /* Analyze b16x8, b*/
38
40
 
39
41
typedef struct XavsContext {
 
42
    AVClass        *class;
40
43
    xavs_param_t    params;
41
44
    xavs_t         *enc;
42
45
    xavs_picture_t  pic;
53
56
    int fast_pskip;
54
57
    int mbtree;
55
58
    int mixed_refs;
 
59
 
 
60
    int64_t *pts_buffer;
 
61
    int out_frame_count;
56
62
} XavsContext;
57
63
 
58
64
static void XAVS_log(void *p, int level, const char *fmt, va_list args)
70
76
    av_vlog(p, level_map[level], fmt, args);
71
77
}
72
78
 
73
 
static int encode_nals(AVCodecContext *ctx, uint8_t *buf,
74
 
                       int size, xavs_nal_t *nals,
75
 
                       int nnal, int skip_sei)
 
79
static int encode_nals(AVCodecContext *ctx, AVPacket *pkt,
 
80
                       xavs_nal_t *nals, int nnal)
76
81
{
77
82
    XavsContext *x4 = ctx->priv_data;
78
 
    uint8_t *p = buf;
79
 
    int i, s;
 
83
    uint8_t *p;
 
84
    int i, s, ret, size = x4->sei_size + FF_MIN_BUFFER_SIZE;
 
85
 
 
86
    if (!nnal)
 
87
        return 0;
 
88
 
 
89
    for (i = 0; i < nnal; i++)
 
90
        size += nals[i].i_payload;
 
91
 
 
92
    if ((ret = ff_alloc_packet(pkt, size)) < 0) {
 
93
        av_log(ctx, AV_LOG_ERROR, "Error getting output packet of size %d.\n", size);
 
94
        return ret;
 
95
    }
 
96
    p = pkt->data;
80
97
 
81
98
    /* Write the SEI as part of the first frame. */
82
99
    if (x4->sei_size > 0 && nnal > 0) {
86
103
    }
87
104
 
88
105
    for (i = 0; i < nnal; i++) {
89
 
        /* Don't put the SEI in extradata. */
90
 
        if (skip_sei && nals[i].i_type == NAL_SEI) {
91
 
            x4->sei = av_malloc( 5 + nals[i].i_payload * 4 / 3 );
92
 
            if (xavs_nal_encode(x4->sei, &x4->sei_size, 1, nals + i) < 0)
93
 
                return -1;
94
 
 
95
 
            continue;
96
 
        }
97
106
        s = xavs_nal_encode(p, &size, 1, nals + i);
98
107
        if (s < 0)
99
108
            return -1;
100
109
        p += s;
101
110
    }
 
111
    pkt->size = p - pkt->data;
102
112
 
103
 
    return p - buf;
 
113
    return 1;
104
114
}
105
115
 
106
 
static int XAVS_frame(AVCodecContext *ctx, uint8_t *buf,
107
 
                      int bufsize, void *data)
 
116
static int XAVS_frame(AVCodecContext *ctx, AVPacket *pkt,
 
117
                      const AVFrame *frame, int *got_packet)
108
118
{
109
119
    XavsContext *x4 = ctx->priv_data;
110
 
    AVFrame *frame = data;
111
120
    xavs_nal_t *nal;
112
 
    int nnal, i;
 
121
    int nnal, i, ret;
113
122
    xavs_picture_t pic_out;
114
123
 
115
124
    x4->pic.img.i_csp   = XAVS_CSP_I420;
123
132
 
124
133
        x4->pic.i_pts  = frame->pts;
125
134
        x4->pic.i_type = XAVS_TYPE_AUTO;
 
135
        x4->pts_buffer[ctx->frame_number % (ctx->max_b_frames+1)] = frame->pts;
126
136
    }
127
137
 
128
138
    if (xavs_encoder_encode(x4->enc, &nal, &nnal,
129
139
                            frame? &x4->pic: NULL, &pic_out) < 0)
130
140
    return -1;
131
141
 
132
 
    bufsize = encode_nals(ctx, buf, bufsize, nal, nnal, 0);
 
142
    ret = encode_nals(ctx, pkt, nal, nnal);
133
143
 
134
 
    if (bufsize < 0)
 
144
    if (ret < 0)
135
145
        return -1;
136
146
 
137
 
    if (!bufsize && !frame && !(x4->end_of_stream)){
138
 
        buf[bufsize]   = 0x0;
139
 
        buf[bufsize+1] = 0x0;
140
 
        buf[bufsize+2] = 0x01;
141
 
        buf[bufsize+3] = 0xb1;
142
 
        bufsize += 4;
143
 
        x4->end_of_stream = END_OF_STREAM;
144
 
        return bufsize;
 
147
    if (!ret) {
 
148
        if (!frame && !(x4->end_of_stream)) {
 
149
            if ((ret = ff_alloc_packet(pkt, 4)) < 0)
 
150
                return ret;
 
151
 
 
152
            pkt->data[0] = 0x0;
 
153
            pkt->data[1] = 0x0;
 
154
            pkt->data[2] = 0x01;
 
155
            pkt->data[3] = 0xb1;
 
156
            pkt->dts = 2*x4->pts_buffer[(x4->out_frame_count-1)%(ctx->max_b_frames+1)] -
 
157
                       x4->pts_buffer[(x4->out_frame_count-2)%(ctx->max_b_frames+1)];
 
158
            x4->end_of_stream = END_OF_STREAM;
 
159
            *got_packet = 1;
 
160
        }
 
161
        return 0;
145
162
    }
146
 
    /* FIXME: libxavs now provides DTS */
147
 
    /* but AVFrame doesn't have a field for it. */
 
163
 
148
164
    x4->out_pic.pts = pic_out.i_pts;
 
165
    pkt->pts = pic_out.i_pts;
 
166
    if (ctx->has_b_frames) {
 
167
        if (!x4->out_frame_count)
 
168
            pkt->dts = pkt->pts - (x4->pts_buffer[1] - x4->pts_buffer[0]);
 
169
        else
 
170
            pkt->dts = x4->pts_buffer[(x4->out_frame_count-1)%(ctx->max_b_frames+1)];
 
171
    } else
 
172
        pkt->dts = pkt->pts;
149
173
 
150
174
    switch (pic_out.i_type) {
151
175
    case XAVS_TYPE_IDR:
163
187
 
164
188
    /* There is no IDR frame in AVS JiZhun */
165
189
    /* Sequence header is used as a flag */
166
 
    x4->out_pic.key_frame = pic_out.i_type == XAVS_TYPE_I;
 
190
    if (pic_out.i_type == XAVS_TYPE_I) {
 
191
        x4->out_pic.key_frame = 1;
 
192
        pkt->flags |= AV_PKT_FLAG_KEY;
 
193
    }
167
194
 
168
195
    x4->out_pic.quality   = (pic_out.i_qpplus1 - 1) * FF_QP2LAMBDA;
169
196
 
170
 
    return bufsize;
 
197
    x4->out_frame_count++;
 
198
    *got_packet = ret;
 
199
    return 0;
171
200
}
172
201
 
173
202
static av_cold int XAVS_close(AVCodecContext *avctx)
176
205
 
177
206
    av_freep(&avctx->extradata);
178
207
    av_free(x4->sei);
 
208
    av_freep(&x4->pts_buffer);
179
209
 
180
210
    if (x4->enc)
181
211
        xavs_encoder_close(x4->enc);
203
233
    if (avctx->flags & CODEC_FLAG_PASS2) {
204
234
        x4->params.rc.b_stat_read = 1;
205
235
    } else {
206
 
#if FF_API_X264_GLOBAL_OPTS
207
 
        if (avctx->crf) {
208
 
            x4->params.rc.i_rc_method   = XAVS_RC_CRF;
209
 
            x4->params.rc.f_rf_constant = avctx->crf;
210
 
        } else if (avctx->cqp > -1) {
211
 
            x4->params.rc.i_rc_method   = XAVS_RC_CQP;
212
 
            x4->params.rc.i_qp_constant = avctx->cqp;
213
 
        }
214
 
#endif
215
 
 
216
236
        if (x4->crf >= 0) {
217
237
            x4->params.rc.i_rc_method   = XAVS_RC_CRF;
218
238
            x4->params.rc.f_rf_constant = x4->crf;
222
242
        }
223
243
    }
224
244
 
225
 
#if FF_API_X264_GLOBAL_OPTS
226
 
    if (avctx->bframebias)
227
 
        x4->params.i_bframe_bias              = avctx->bframebias;
228
 
    if (avctx->deblockalpha)
229
 
        x4->params.i_deblocking_filter_alphac0 = avctx->deblockalpha;
230
 
    if (avctx->deblockbeta)
231
 
        x4->params.i_deblocking_filter_beta    = avctx->deblockbeta;
232
 
    if (avctx->complexityblur >= 0)
233
 
        x4->params.rc.f_complexity_blur        = avctx->complexityblur;
234
 
    if (avctx->directpred >= 0)
235
 
        x4->params.analyse.i_direct_mv_pred    = avctx->directpred;
236
 
    if (avctx->partitions) {
237
 
        if (avctx->partitions & XAVS_PART_I8X8)
238
 
            x4->params.analyse.inter |= XAVS_ANALYSE_I8x8;
239
 
        if (avctx->partitions & XAVS_PART_P8X8)
240
 
            x4->params.analyse.inter |= XAVS_ANALYSE_PSUB16x16;
241
 
        if (avctx->partitions & XAVS_PART_B8X8)
242
 
            x4->params.analyse.inter |= XAVS_ANALYSE_BSUB16x16;
243
 
    }
244
 
    x4->params.rc.b_mb_tree               = !!(avctx->flags2 & CODEC_FLAG2_MBTREE);
245
 
    x4->params.b_aud          = avctx->flags2 & CODEC_FLAG2_AUD;
246
 
    x4->params.analyse.b_mixed_references = avctx->flags2 & CODEC_FLAG2_MIXED_REFS;
247
 
    x4->params.analyse.b_fast_pskip       = avctx->flags2 & CODEC_FLAG2_FASTPSKIP;
248
 
    x4->params.analyse.b_weighted_bipred = avctx->flags2 & CODEC_FLAG2_WPRED;
249
 
#endif
250
 
 
251
245
    if (x4->aud >= 0)
252
246
        x4->params.b_aud                      = x4->aud;
253
247
    if (x4->mbtree >= 0)
360
354
    if (!x4->enc)
361
355
        return -1;
362
356
 
 
357
    if (!(x4->pts_buffer = av_mallocz((avctx->max_b_frames+1) * sizeof(*x4->pts_buffer))))
 
358
        return AVERROR(ENOMEM);
 
359
 
363
360
    avctx->coded_frame = &x4->out_pic;
364
361
    /* TAG: Do we have GLOBAL HEADER in AVS */
365
362
    /* We Have PPS and SPS in AVS */
366
363
    if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) {
367
364
        xavs_nal_t *nal;
368
 
        int nnal, s;
 
365
        int nnal, s, i, size;
 
366
        uint8_t *p;
369
367
 
370
368
        s = xavs_encoder_headers(x4->enc, &nal, &nnal);
371
369
 
372
 
        avctx->extradata      = av_malloc(s);
373
 
        avctx->extradata_size = encode_nals(avctx, avctx->extradata, s, nal, nnal, 1);
 
370
        avctx->extradata = p = av_malloc(s);
 
371
        for (i = 0; i < nnal; i++) {
 
372
            /* Don't put the SEI in extradata. */
 
373
            if (nal[i].i_type == NAL_SEI) {
 
374
                x4->sei = av_malloc( 5 + nal[i].i_payload * 4 / 3 );
 
375
                if (xavs_nal_encode(x4->sei, &x4->sei_size, 1, nal + i) < 0)
 
376
                    return -1;
 
377
 
 
378
                continue;
 
379
            }
 
380
            size = xavs_nal_encode(p, &s, 1, nal + i);
 
381
            if (size < 0)
 
382
                return -1;
 
383
            p += size;
 
384
        }
 
385
        avctx->extradata_size = p - avctx->extradata;
374
386
    }
375
387
    return 0;
376
388
}
379
391
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
380
392
static const AVOption options[] = {
381
393
    { "crf",           "Select the quality for constant quality mode",    OFFSET(crf),           AV_OPT_TYPE_FLOAT,  {-1 }, -1, FLT_MAX, VE },
382
 
    { "qp",            "Constant quantization parameter rate control method",OFFSET(cqp),        AV_OPT_TYPE_INT,    {-1 }, -1, INT_MAX, VE },
383
 
    { "b-bias",        "Influences how often B-frames are used",          OFFSET(b_bias),        AV_OPT_TYPE_INT,    {INT_MIN}, INT_MIN, INT_MAX, VE },
 
394
    { "qp",            "Constant quantization parameter rate control method",OFFSET(cqp),        AV_OPT_TYPE_INT,    {.i64 = -1 }, -1, INT_MAX, VE },
 
395
    { "b-bias",        "Influences how often B-frames are used",          OFFSET(b_bias),        AV_OPT_TYPE_INT,    {.i64 = INT_MIN}, INT_MIN, INT_MAX, VE },
384
396
    { "cplxblur",      "Reduce fluctuations in QP (before curve compression)", OFFSET(cplxblur), AV_OPT_TYPE_FLOAT,  {-1 }, -1, FLT_MAX, VE},
385
 
    { "direct-pred",   "Direct MV prediction mode",                       OFFSET(direct_pred),   AV_OPT_TYPE_INT,    {-1 }, -1, INT_MAX, VE, "direct-pred" },
386
 
    { "none",          NULL,      0,    AV_OPT_TYPE_CONST, { XAVS_DIRECT_PRED_NONE },     0, 0, VE, "direct-pred" },
387
 
    { "spatial",       NULL,      0,    AV_OPT_TYPE_CONST, { XAVS_DIRECT_PRED_SPATIAL },  0, 0, VE, "direct-pred" },
388
 
    { "temporal",      NULL,      0,    AV_OPT_TYPE_CONST, { XAVS_DIRECT_PRED_TEMPORAL }, 0, 0, VE, "direct-pred" },
389
 
    { "auto",          NULL,      0,    AV_OPT_TYPE_CONST, { XAVS_DIRECT_PRED_AUTO },     0, 0, VE, "direct-pred" },
390
 
    { "aud",           "Use access unit delimiters.",                     OFFSET(aud),           AV_OPT_TYPE_INT,    {-1 }, -1, 1, VE},
391
 
    { "mbtree",        "Use macroblock tree ratecontrol.",                OFFSET(mbtree),        AV_OPT_TYPE_INT,    {-1 }, -1, 1, VE},
392
 
    { "mixed-refs",    "One reference per partition, as opposed to one reference per macroblock", OFFSET(mixed_refs), AV_OPT_TYPE_INT, {-1}, -1, 1, VE },
393
 
    { "fast-pskip",    NULL,                                              OFFSET(fast_pskip),    AV_OPT_TYPE_INT,    {-1 }, -1, 1, VE},
 
397
    { "direct-pred",   "Direct MV prediction mode",                       OFFSET(direct_pred),   AV_OPT_TYPE_INT,    {.i64 = -1 }, -1, INT_MAX, VE, "direct-pred" },
 
398
    { "none",          NULL,      0,    AV_OPT_TYPE_CONST, { .i64 = XAVS_DIRECT_PRED_NONE },     0, 0, VE, "direct-pred" },
 
399
    { "spatial",       NULL,      0,    AV_OPT_TYPE_CONST, { .i64 = XAVS_DIRECT_PRED_SPATIAL },  0, 0, VE, "direct-pred" },
 
400
    { "temporal",      NULL,      0,    AV_OPT_TYPE_CONST, { .i64 = XAVS_DIRECT_PRED_TEMPORAL }, 0, 0, VE, "direct-pred" },
 
401
    { "auto",          NULL,      0,    AV_OPT_TYPE_CONST, { .i64 = XAVS_DIRECT_PRED_AUTO },     0, 0, VE, "direct-pred" },
 
402
    { "aud",           "Use access unit delimiters.",                     OFFSET(aud),           AV_OPT_TYPE_INT,    {.i64 = -1 }, -1, 1, VE},
 
403
    { "mbtree",        "Use macroblock tree ratecontrol.",                OFFSET(mbtree),        AV_OPT_TYPE_INT,    {.i64 = -1 }, -1, 1, VE},
 
404
    { "mixed-refs",    "One reference per partition, as opposed to one reference per macroblock", OFFSET(mixed_refs), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, VE },
 
405
    { "fast-pskip",    NULL,                                              OFFSET(fast_pskip),    AV_OPT_TYPE_INT,    {.i64 = -1 }, -1, 1, VE},
394
406
    { NULL },
395
407
};
396
408
 
409
421
AVCodec ff_libxavs_encoder = {
410
422
    .name           = "libxavs",
411
423
    .type           = AVMEDIA_TYPE_VIDEO,
412
 
    .id             = CODEC_ID_CAVS,
 
424
    .id             = AV_CODEC_ID_CAVS,
413
425
    .priv_data_size = sizeof(XavsContext),
414
426
    .init           = XAVS_init,
415
 
    .encode         = XAVS_frame,
 
427
    .encode2        = XAVS_frame,
416
428
    .close          = XAVS_close,
417
429
    .capabilities   = CODEC_CAP_DELAY | CODEC_CAP_AUTO_THREADS,
418
 
    .pix_fmts       = (const enum PixelFormat[]) { PIX_FMT_YUV420P, PIX_FMT_NONE },
419
 
    .long_name      = NULL_IF_CONFIG_SMALL("libxavs - the Chinese Audio Video Standard Encoder"),
 
430
    .pix_fmts       = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE },
 
431
    .long_name      = NULL_IF_CONFIG_SMALL("libxavs Chinese AVS (Audio Video Standard)"),
420
432
    .priv_class     = &class,
421
433
    .defaults       = xavs_defaults,
422
434
};
423