Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5362 serge 1
/*
2
 * Copyright (c) 2012 Intel Corporation. All Rights Reserved.
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a
5
 * copy of this software and associated documentation files (the
6
 * "Software"), to deal in the Software without restriction, including
7
 * without limitation the rights to use, copy, modify, merge, publish,
8
 * distribute, sub license, and/or sell copies of the Software, and to
9
 * permit persons to whom the Software is furnished to do so, subject to
10
 * the following conditions:
11
 *
12
 * The above copyright notice and this permission notice (including the
13
 * next paragraph) shall be included in all copies or substantial portions
14
 * of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19
 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
 */
24
/*
25
 * Simple AVC encoder based on libVA.
26
 *
27
 * Usage:
28
 * ./avcenc     [qp]
29
 */
30
 
31
#include "sysdeps.h"
32
#include 
33
#include 
34
#include 
35
#include 
36
#include 
37
 
38
#include 
39
#include 
40
#include 
41
#include 
42
#include 
43
#include 
44
 
45
#include 
46
 
47
#include 
48
#include 
49
#include "va_display.h"
50
 
51
#define NAL_REF_IDC_NONE        0
52
#define NAL_REF_IDC_LOW         1
53
#define NAL_REF_IDC_MEDIUM      2
54
#define NAL_REF_IDC_HIGH        3
55
 
56
#define NAL_NON_IDR             1
57
#define NAL_IDR                 5
58
#define NAL_SPS                 7
59
#define NAL_PPS                 8
60
#define NAL_SEI			6
61
 
62
#define SLICE_TYPE_P            0
63
#define SLICE_TYPE_B            1
64
#define SLICE_TYPE_I            2
65
 
66
#define FRAME_IDR 7
67
 
68
#define ENTROPY_MODE_CAVLC      0
69
#define ENTROPY_MODE_CABAC      1
70
 
71
#define PROFILE_IDC_BASELINE    66
72
#define PROFILE_IDC_MAIN        77
73
#define PROFILE_IDC_HIGH        100
74
 
75
#define CHECK_VASTATUS(va_status,func)                                  \
76
    if (va_status != VA_STATUS_SUCCESS) {                               \
77
        fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \
78
        exit(1);                                                        \
79
    }
80
 
81
static VADisplay va_dpy;
82
 
83
static int picture_width, picture_width_in_mbs;
84
static int picture_height, picture_height_in_mbs;
85
static int frame_size;
86
static unsigned char *newImageBuffer = 0;
87
 
88
static int qp_value = 26;
89
 
90
static int intra_period = 30;
91
static int frame_bit_rate = -1;
92
static int frame_rate = 30;
93
static int ip_period = 1;
94
 
95
#define MAX_SLICES      32
96
 
97
 
98
static  unsigned int MaxFrameNum = (1<<12);
99
static  unsigned int MaxPicOrderCntLsb = (1<<8);
100
static  unsigned int Log2MaxFrameNum = 12;
101
static  unsigned int Log2MaxPicOrderCntLsb = 8;
102
 
103
static int
104
build_packed_pic_buffer(unsigned char **header_buffer);
105
 
106
static int
107
build_packed_seq_buffer(unsigned char **header_buffer);
108
 
109
static int
110
build_packed_sei_pic_timing(unsigned int cpb_removal_length,
111
				unsigned int dpb_output_length,
112
				unsigned char **sei_buffer);
113
 
114
static int
115
build_packed_idr_sei_buffer_timing(unsigned int init_cpb_removal_delay_length,
116
				unsigned int cpb_removal_length,
117
				unsigned int dpb_output_length,
118
				unsigned char **sei_buffer);
119
 
120
struct upload_thread_param
121
{
122
    FILE *yuv_fp;
123
    VASurfaceID surface_id;
124
};
125
 
126
static void
127
upload_yuv_to_surface(FILE *yuv_fp, VASurfaceID surface_id);
128
 
129
static struct {
130
    VAProfile profile;
131
    int constraint_set_flag;
132
    VAEncSequenceParameterBufferH264 seq_param;
133
    VAEncPictureParameterBufferH264 pic_param;
134
    VAEncSliceParameterBufferH264 slice_param[MAX_SLICES];
135
    VAContextID context_id;
136
    VAConfigID config_id;
137
    VABufferID seq_param_buf_id;                /* Sequence level parameter */
138
    VABufferID pic_param_buf_id;                /* Picture level parameter */
139
    VABufferID slice_param_buf_id[MAX_SLICES];  /* Slice level parameter, multil slices */
140
    VABufferID codedbuf_buf_id;                 /* Output buffer, compressed data */
141
    VABufferID packed_seq_header_param_buf_id;
142
    VABufferID packed_seq_buf_id;
143
    VABufferID packed_pic_header_param_buf_id;
144
    VABufferID packed_pic_buf_id;
145
    VABufferID packed_sei_header_param_buf_id;   /* the SEI buffer */
146
    VABufferID packed_sei_buf_id;
147
    VABufferID misc_parameter_hrd_buf_id;
148
 
149
    int num_slices;
150
    int codedbuf_i_size;
151
    int codedbuf_pb_size;
152
    int current_input_surface;
153
    int rate_control_method;
154
    struct upload_thread_param upload_thread_param;
155
    pthread_t upload_thread_id;
156
    int upload_thread_value;
157
    int i_initial_cpb_removal_delay;
158
    int i_initial_cpb_removal_delay_offset;
159
    int i_initial_cpb_removal_delay_length;
160
    int i_cpb_removal_delay;
161
    int i_cpb_removal_delay_length;
162
    int i_dpb_output_delay_length;
163
    int time_offset_length;
164
 
165
    unsigned long long idr_frame_num;
166
    unsigned long long prev_idr_cpb_removal;
167
    unsigned long long current_idr_cpb_removal;
168
    unsigned long long current_cpb_removal;
169
    /* This is relative to the current_cpb_removal */
170
    unsigned int current_dpb_removal_delta;
171
} avcenc_context;
172
 
173
static  VAPictureH264 ReferenceFrames[16], RefPicList0[32], RefPicList1[32];
174
 
175
static void create_encode_pipe()
176
{
177
    VAEntrypoint entrypoints[5];
178
    int num_entrypoints,slice_entrypoint;
179
    VAConfigAttrib attrib[2];
180
    int major_ver, minor_ver;
181
    VAStatus va_status;
182
 
183
    va_dpy = va_open_display();
184
    va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
185
    CHECK_VASTATUS(va_status, "vaInitialize");
186
 
187
    vaQueryConfigEntrypoints(va_dpy, avcenc_context.profile, entrypoints,
188
                             &num_entrypoints);
189
 
190
    for	(slice_entrypoint = 0; slice_entrypoint < num_entrypoints; slice_entrypoint++) {
191
        if (entrypoints[slice_entrypoint] == VAEntrypointEncSlice)
192
            break;
193
    }
194
 
195
    if (slice_entrypoint == num_entrypoints) {
196
        /* not find Slice entry point */
197
        assert(0);
198
    }
199
 
200
    /* find out the format for the render target, and rate control mode */
201
    attrib[0].type = VAConfigAttribRTFormat;
202
    attrib[1].type = VAConfigAttribRateControl;
203
    vaGetConfigAttributes(va_dpy, avcenc_context.profile, VAEntrypointEncSlice,
204
                          &attrib[0], 2);
205
 
206
    if ((attrib[0].value & VA_RT_FORMAT_YUV420) == 0) {
207
        /* not find desired YUV420 RT format */
208
        assert(0);
209
    }
210
 
211
    if ((attrib[1].value & avcenc_context.rate_control_method) == 0) {
212
        /* Can't find matched RC mode */
213
        printf("Can't find the desired RC mode, exit\n");
214
        assert(0);
215
    }
216
 
217
    attrib[0].value = VA_RT_FORMAT_YUV420; /* set to desired RT format */
218
    attrib[1].value = avcenc_context.rate_control_method; /* set to desired RC mode */
219
 
220
    va_status = vaCreateConfig(va_dpy, avcenc_context.profile, VAEntrypointEncSlice,
221
                               &attrib[0], 2,&avcenc_context.config_id);
222
    CHECK_VASTATUS(va_status, "vaCreateConfig");
223
 
224
    /* Create a context for this decode pipe */
225
    va_status = vaCreateContext(va_dpy, avcenc_context.config_id,
226
                                picture_width, picture_height,
227
                                VA_PROGRESSIVE,
228
                                0, 0,
229
                                &avcenc_context.context_id);
230
    CHECK_VASTATUS(va_status, "vaCreateContext");
231
}
232
 
233
static void destory_encode_pipe()
234
{
235
    vaDestroyContext(va_dpy,avcenc_context.context_id);
236
    vaDestroyConfig(va_dpy,avcenc_context.config_id);
237
    vaTerminate(va_dpy);
238
    va_close_display(va_dpy);
239
}
240
 
241
/***************************************************
242
 *
243
 *  The encode pipe resource define
244
 *
245
 ***************************************************/
246
#define SID_INPUT_PICTURE_0                     0
247
#define SID_INPUT_PICTURE_1                     1
248
#define SID_REFERENCE_PICTURE_L0                2
249
#define SID_REFERENCE_PICTURE_L1                3
250
#define SID_RECON_PICTURE                       4
251
#define SID_NUMBER                              SID_RECON_PICTURE + 1
252
 
253
#define SURFACE_NUM 16 /* 16 surfaces for reference */
254
 
255
static  VASurfaceID surface_ids[SID_NUMBER];
256
static  VASurfaceID ref_surface[SURFACE_NUM];
257
 
258
static  unsigned long long current_frame_display = 0;
259
static  unsigned long long current_IDR_display = 0;
260
 
261
static  VAPictureH264 CurrentCurrPic;
262
 
263
#define current_slot (current_frame_display % SURFACE_NUM)
264
 
265
static int frame_number;
266
static unsigned long long enc_frame_number;
267
static int current_frame_type;
268
static int current_frame_num;
269
static unsigned int current_poc;
270
 
271
static  unsigned int num_ref_frames = 2;
272
static  unsigned int numShortTerm = 0;
273
/***************************************************/
274
 
275
static void *
276
upload_thread_function(void *data)
277
{
278
    struct upload_thread_param *param = data;
279
 
280
    upload_yuv_to_surface(param->yuv_fp, param->surface_id);
281
 
282
    return NULL;
283
}
284
 
285
static void alloc_encode_resource(FILE *yuv_fp)
286
{
287
    VAStatus va_status;
288
 
289
    // Create surface
290
    va_status = vaCreateSurfaces(
291
        va_dpy,
292
        VA_RT_FORMAT_YUV420, picture_width, picture_height,
293
        surface_ids, SID_NUMBER,
294
        NULL, 0
295
    );
296
 
297
    CHECK_VASTATUS(va_status, "vaCreateSurfaces");
298
 
299
    // Create surface
300
    va_status = vaCreateSurfaces(
301
        va_dpy,
302
        VA_RT_FORMAT_YUV420, picture_width, picture_height,
303
        ref_surface, SURFACE_NUM,
304
        NULL, 0
305
    );
306
 
307
    CHECK_VASTATUS(va_status, "vaCreateSurfaces");
308
 
309
 
310
    newImageBuffer = (unsigned char *)malloc(frame_size);
311
 
312
    /* firstly upload YUV data to SID_INPUT_PICTURE_1 */
313
    avcenc_context.upload_thread_param.yuv_fp = yuv_fp;
314
    avcenc_context.upload_thread_param.surface_id = surface_ids[SID_INPUT_PICTURE_1];
315
 
316
    avcenc_context.upload_thread_value = pthread_create(&avcenc_context.upload_thread_id,
317
                                                        NULL,
318
                                                        upload_thread_function,
319
                                                        (void*)&avcenc_context.upload_thread_param);
320
}
321
 
322
static void release_encode_resource()
323
{
324
    pthread_join(avcenc_context.upload_thread_id, NULL);
325
    free(newImageBuffer);
326
 
327
    // Release all the surfaces resource
328
    vaDestroySurfaces(va_dpy, surface_ids, SID_NUMBER);
329
    // Release all the reference surfaces
330
    vaDestroySurfaces(va_dpy, ref_surface, SURFACE_NUM);
331
}
332
 
333
static void avcenc_update_sei_param(int is_idr)
334
{
335
	VAEncPackedHeaderParameterBuffer packed_header_param_buffer;
336
	unsigned int length_in_bits;
337
	unsigned char *packed_sei_buffer = NULL;
338
	VAStatus va_status;
339
 
340
        if (is_idr)
341
	    length_in_bits = build_packed_idr_sei_buffer_timing(
342
				avcenc_context.i_initial_cpb_removal_delay_length,
343
				avcenc_context.i_cpb_removal_delay_length,
344
				avcenc_context.i_dpb_output_delay_length,
345
				&packed_sei_buffer);
346
       else
347
	    length_in_bits = build_packed_sei_pic_timing(
348
				avcenc_context.i_cpb_removal_delay_length,
349
				avcenc_context.i_dpb_output_delay_length,
350
				&packed_sei_buffer);
351
 
352
	packed_header_param_buffer.type = VAEncPackedHeaderH264_SEI;
353
	packed_header_param_buffer.bit_length = length_in_bits;
354
	packed_header_param_buffer.has_emulation_bytes = 0;
355
 
356
	va_status = vaCreateBuffer(va_dpy,
357
				avcenc_context.context_id,
358
				VAEncPackedHeaderParameterBufferType,
359
				sizeof(packed_header_param_buffer), 1, &packed_header_param_buffer,
360
				&avcenc_context.packed_sei_header_param_buf_id);
361
	CHECK_VASTATUS(va_status,"vaCreateBuffer");
362
 
363
	va_status = vaCreateBuffer(va_dpy,
364
				avcenc_context.context_id,
365
				VAEncPackedHeaderDataBufferType,
366
				(length_in_bits + 7) / 8, 1, packed_sei_buffer,
367
				&avcenc_context.packed_sei_buf_id);
368
	CHECK_VASTATUS(va_status,"vaCreateBuffer");
369
	free(packed_sei_buffer);
370
	return;
371
}
372
 
373
#define partition(ref, field, key, ascending)   \
374
    while (i <= j) {                            \
375
        if (ascending) {                        \
376
            while (ref[i].field < key)          \
377
                i++;                            \
378
            while (ref[j].field > key)          \
379
                j--;                            \
380
        } else {                                \
381
            while (ref[i].field > key)          \
382
                i++;                            \
383
            while (ref[j].field < key)          \
384
                j--;                            \
385
        }                                       \
386
        if (i <= j) {                           \
387
            tmp = ref[i];                       \
388
            ref[i] = ref[j];                    \
389
            ref[j] = tmp;                       \
390
            i++;                                \
391
            j--;                                \
392
        }                                       \
393
    }                                           \
394
 
395
static void sort_one(VAPictureH264 ref[], int left, int right,
396
                     int ascending, int frame_idx)
397
{
398
    int i = left, j = right;
399
    unsigned int key;
400
    VAPictureH264 tmp;
401
 
402
    if (frame_idx) {
403
        key = ref[(left + right) / 2].frame_idx;
404
        partition(ref, frame_idx, key, ascending);
405
    } else {
406
        key = ref[(left + right) / 2].TopFieldOrderCnt;
407
        partition(ref, TopFieldOrderCnt, (signed int)key, ascending);
408
    }
409
 
410
    /* recursion */
411
    if (left < j)
412
        sort_one(ref, left, j, ascending, frame_idx);
413
 
414
    if (i < right)
415
        sort_one(ref, i, right, ascending, frame_idx);
416
}
417
 
418
static void sort_two(VAPictureH264 ref[], int left, int right, unsigned int key, unsigned int frame_idx,
419
                     int partition_ascending, int list0_ascending, int list1_ascending)
420
{
421
    int i = left, j = right;
422
    VAPictureH264 tmp;
423
 
424
    if (frame_idx) {
425
        partition(ref, frame_idx, key, partition_ascending);
426
    } else {
427
        partition(ref, TopFieldOrderCnt, (signed int)key, partition_ascending);
428
    }
429
 
430
    sort_one(ref, left, i-1, list0_ascending, frame_idx);
431
    sort_one(ref, j+1, right, list1_ascending, frame_idx);
432
}
433
 
434
static int update_RefPicList()
435
{
436
 
437
    if (current_frame_type == SLICE_TYPE_P) {
438
        memcpy(RefPicList0, ReferenceFrames, numShortTerm * sizeof(VAPictureH264));
439
        sort_one(RefPicList0, 0, numShortTerm-1, 0, 1);
440
    }
441
 
442
    if (current_frame_type == SLICE_TYPE_B) {
443
        memcpy(RefPicList0, ReferenceFrames, numShortTerm * sizeof(VAPictureH264));
444
        sort_two(RefPicList0, 0, numShortTerm-1, current_poc, 0,
445
                 1, 0, 1);
446
 
447
        memcpy(RefPicList1, ReferenceFrames, numShortTerm * sizeof(VAPictureH264));
448
        sort_two(RefPicList1, 0, numShortTerm-1, current_poc, 0,
449
                 0, 1, 0);
450
    }
451
 
452
    return 0;
453
}
454
 
455
static int calc_poc(int pic_order_cnt_lsb)
456
{
457
    static int PicOrderCntMsb_ref = 0, pic_order_cnt_lsb_ref = 0;
458
    int prevPicOrderCntMsb, prevPicOrderCntLsb;
459
    int PicOrderCntMsb, TopFieldOrderCnt;
460
 
461
    if (current_frame_type == FRAME_IDR)
462
        prevPicOrderCntMsb = prevPicOrderCntLsb = 0;
463
    else {
464
        prevPicOrderCntMsb = PicOrderCntMsb_ref;
465
        prevPicOrderCntLsb = pic_order_cnt_lsb_ref;
466
    }
467
 
468
    if ((pic_order_cnt_lsb < prevPicOrderCntLsb) &&
469
        ((prevPicOrderCntLsb - pic_order_cnt_lsb) >= (int)(MaxPicOrderCntLsb / 2)))
470
        PicOrderCntMsb = prevPicOrderCntMsb + MaxPicOrderCntLsb;
471
    else if ((pic_order_cnt_lsb > prevPicOrderCntLsb) &&
472
             ((pic_order_cnt_lsb - prevPicOrderCntLsb) > (int)(MaxPicOrderCntLsb / 2)))
473
        PicOrderCntMsb = prevPicOrderCntMsb - MaxPicOrderCntLsb;
474
    else
475
        PicOrderCntMsb = prevPicOrderCntMsb;
476
 
477
    TopFieldOrderCnt = PicOrderCntMsb + pic_order_cnt_lsb;
478
 
479
    if (current_frame_type != SLICE_TYPE_B) {
480
        PicOrderCntMsb_ref = PicOrderCntMsb;
481
        pic_order_cnt_lsb_ref = pic_order_cnt_lsb;
482
    }
483
 
484
    return TopFieldOrderCnt;
485
}
486
 
487
static void avcenc_update_picture_parameter(int slice_type, int is_idr)
488
{
489
    VAEncPictureParameterBufferH264 *pic_param;
490
    VAStatus va_status;
491
 
492
    // Picture level
493
    pic_param = &avcenc_context.pic_param;
494
 
495
    pic_param->CurrPic.picture_id = ref_surface[current_slot];
496
    pic_param->CurrPic.frame_idx = current_frame_num;
497
    pic_param->CurrPic.flags = 0;
498
 
499
    pic_param->CurrPic.TopFieldOrderCnt = current_poc;
500
    pic_param->CurrPic.BottomFieldOrderCnt = pic_param->CurrPic.TopFieldOrderCnt;
501
 
502
    assert(avcenc_context.codedbuf_buf_id != VA_INVALID_ID);
503
    pic_param->coded_buf = avcenc_context.codedbuf_buf_id;
504
    pic_param->frame_num = current_frame_num;
505
    pic_param->pic_fields.bits.idr_pic_flag = !!is_idr;
506
    pic_param->pic_fields.bits.reference_pic_flag = (slice_type != SLICE_TYPE_B);
507
    CurrentCurrPic = pic_param->CurrPic;
508
 
509
    if (slice_type == SLICE_TYPE_P || slice_type == SLICE_TYPE_B)
510
	memset(pic_param->ReferenceFrames, 0xff, 16 * sizeof(VAPictureH264)); /* invalid all */
511
 
512
    if ((slice_type == SLICE_TYPE_P) || (slice_type == SLICE_TYPE_B)) {
513
	pic_param->ReferenceFrames[0] = RefPicList0[0];
514
    }
515
    if (slice_type == SLICE_TYPE_B) {
516
	pic_param->ReferenceFrames[1] = RefPicList1[0];
517
    }
518
 
519
    va_status = vaCreateBuffer(va_dpy,
520
                               avcenc_context.context_id,
521
                               VAEncPictureParameterBufferType,
522
                               sizeof(*pic_param), 1, pic_param,
523
                               &avcenc_context.pic_param_buf_id);
524
    CHECK_VASTATUS(va_status,"vaCreateBuffer");
525
 
526
}
527
 
528
#ifndef VA_FOURCC_I420
529
#define VA_FOURCC_I420          0x30323449
530
#endif
531
 
532
static void upload_yuv_to_surface(FILE *yuv_fp, VASurfaceID surface_id)
533
{
534
    VAImage surface_image;
535
    VAStatus va_status;
536
    void *surface_p = NULL;
537
    unsigned char *y_src, *u_src, *v_src;
538
    unsigned char *y_dst, *u_dst, *v_dst;
539
    int y_size = picture_width * picture_height;
540
    int u_size = (picture_width >> 1) * (picture_height >> 1);
541
    int row, col;
542
    size_t n_items;
543
 
544
    do {
545
        n_items = fread(newImageBuffer, frame_size, 1, yuv_fp);
546
    } while (n_items != 1);
547
 
548
    va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
549
    CHECK_VASTATUS(va_status,"vaDeriveImage");
550
 
551
    vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
552
    assert(VA_STATUS_SUCCESS == va_status);
553
 
554
    y_src = newImageBuffer;
555
    u_src = newImageBuffer + y_size; /* UV offset for NV12 */
556
    v_src = newImageBuffer + y_size + u_size;
557
 
558
    y_dst = surface_p + surface_image.offsets[0];
559
    u_dst = surface_p + surface_image.offsets[1]; /* UV offset for NV12 */
560
    v_dst = surface_p + surface_image.offsets[2];
561
 
562
    /* Y plane */
563
    for (row = 0; row < surface_image.height; row++) {
564
        memcpy(y_dst, y_src, surface_image.width);
565
        y_dst += surface_image.pitches[0];
566
        y_src += picture_width;
567
    }
568
 
569
    if (surface_image.format.fourcc == VA_FOURCC_NV12) { /* UV plane */
570
        for (row = 0; row < surface_image.height / 2; row++) {
571
            for (col = 0; col < surface_image.width / 2; col++) {
572
                u_dst[col * 2] = u_src[col];
573
                u_dst[col * 2 + 1] = v_src[col];
574
            }
575
 
576
            u_dst += surface_image.pitches[1];
577
            u_src += (picture_width / 2);
578
            v_src += (picture_width / 2);
579
        }
580
    } else if (surface_image.format.fourcc == VA_FOURCC_YV12 ||
581
               surface_image.format.fourcc == VA_FOURCC_I420) {
582
        const int U = surface_image.format.fourcc == VA_FOURCC_I420 ? 1 : 2;
583
        const int V = surface_image.format.fourcc == VA_FOURCC_I420 ? 2 : 1;
584
 
585
        u_dst = surface_p + surface_image.offsets[U];
586
        v_dst = surface_p + surface_image.offsets[V];
587
 
588
        for (row = 0; row < surface_image.height / 2; row++) {
589
            memcpy(u_dst, u_src, surface_image.width / 2);
590
            memcpy(v_dst, v_src, surface_image.width / 2);
591
            u_dst += surface_image.pitches[U];
592
            v_dst += surface_image.pitches[V];
593
            u_src += (picture_width / 2);
594
            v_src += (picture_width / 2);
595
        }
596
    }
597
 
598
    vaUnmapBuffer(va_dpy, surface_image.buf);
599
    vaDestroyImage(va_dpy, surface_image.image_id);
600
}
601
 
602
static void avcenc_update_slice_parameter(int slice_type)
603
{
604
    VAEncSliceParameterBufferH264 *slice_param;
605
    VAStatus va_status;
606
    int i;
607
 
608
    // Slice level
609
    i = 0;
610
    slice_param = &avcenc_context.slice_param[i];
611
    slice_param->macroblock_address = 0;
612
    slice_param->num_macroblocks = picture_height_in_mbs * picture_width_in_mbs;
613
    slice_param->pic_parameter_set_id = 0;
614
    slice_param->slice_type = slice_type;
615
    slice_param->direct_spatial_mv_pred_flag = 0;
616
    slice_param->num_ref_idx_l0_active_minus1 = 0;      /* FIXME: ??? */
617
    slice_param->num_ref_idx_l1_active_minus1 = 0;
618
    slice_param->cabac_init_idc = 0;
619
    slice_param->slice_qp_delta = 0;
620
    slice_param->disable_deblocking_filter_idc = 0;
621
    slice_param->slice_alpha_c0_offset_div2 = 2;
622
    slice_param->slice_beta_offset_div2 = 2;
623
    slice_param->idr_pic_id = 0;
624
 
625
    /* FIXME: fill other fields */
626
    if ((slice_type == SLICE_TYPE_P) || (slice_type == SLICE_TYPE_B)) {
627
	memset(slice_param->RefPicList0, 0xFF, 32 * sizeof(VAPictureH264));
628
	slice_param->RefPicList0[0] = RefPicList0[0];
629
    }
630
 
631
    if ((slice_type == SLICE_TYPE_B)) {
632
	memset(slice_param->RefPicList1, 0xFF, 32 * sizeof(VAPictureH264));
633
	slice_param->RefPicList1[0] = RefPicList1[0];
634
    }
635
 
636
    va_status = vaCreateBuffer(va_dpy,
637
                               avcenc_context.context_id,
638
                               VAEncSliceParameterBufferType,
639
                               sizeof(*slice_param), 1, slice_param,
640
                               &avcenc_context.slice_param_buf_id[i]);
641
    CHECK_VASTATUS(va_status,"vaCreateBuffer");;
642
    i++;
643
 
644
#if 0
645
    slice_param = &avcenc_context.slice_param[i];
646
    slice_param->macroblock_address = picture_height_in_mbs * picture_width_in_mbs / 2;
647
    slice_param->num_macroblocks = picture_height_in_mbs * picture_width_in_mbs / 2;
648
    slice_param->pic_parameter_set_id = 0;
649
    slice_param->slice_type = slice_type;
650
    slice_param->direct_spatial_mv_pred_flag = 0;
651
    slice_param->num_ref_idx_l0_active_minus1 = 0;      /* FIXME: ??? */
652
    slice_param->num_ref_idx_l1_active_minus1 = 0;
653
    slice_param->cabac_init_idc = 0;
654
    slice_param->slice_qp_delta = 0;
655
    slice_param->disable_deblocking_filter_idc = 0;
656
    slice_param->slice_alpha_c0_offset_div2 = 2;
657
    slice_param->slice_beta_offset_div2 = 2;
658
    slice_param->idr_pic_id = 0;
659
 
660
    /* FIXME: fill other fields */
661
 
662
    va_status = vaCreateBuffer(va_dpy,
663
                               avcenc_context.context_id,
664
                               VAEncSliceParameterBufferType,
665
                               sizeof(*slice_param), 1, slice_param,
666
                               &avcenc_context.slice_param_buf_id[i]);
667
    CHECK_VASTATUS(va_status,"vaCreateBuffer");;
668
    i++;
669
#endif
670
 
671
    avcenc_context.num_slices = i;
672
}
673
 
674
static int update_ReferenceFrames(void)
675
{
676
    int i;
677
 
678
    /* B-frame is not used for reference */
679
    if (current_frame_type == SLICE_TYPE_B)
680
        return 0;
681
 
682
    CurrentCurrPic.flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE;
683
    numShortTerm++;
684
    if (numShortTerm > num_ref_frames)
685
        numShortTerm = num_ref_frames;
686
    for (i=numShortTerm-1; i>0; i--)
687
        ReferenceFrames[i] = ReferenceFrames[i-1];
688
    ReferenceFrames[0] = CurrentCurrPic;
689
 
690
    if (current_frame_type != SLICE_TYPE_B)
691
        current_frame_num++;
692
    if (current_frame_num > MaxFrameNum)
693
        current_frame_num = 0;
694
 
695
    return 0;
696
}
697
 
698
static int begin_picture(FILE *yuv_fp, int frame_num, int display_num, int slice_type, int is_idr)
699
{
700
    VAStatus va_status;
701
 
702
    if (avcenc_context.upload_thread_value != 0) {
703
        fprintf(stderr, "FATAL error!!!\n");
704
        exit(1);
705
    }
706
 
707
    pthread_join(avcenc_context.upload_thread_id, NULL);
708
 
709
    avcenc_context.upload_thread_value = -1;
710
 
711
    if (avcenc_context.current_input_surface == SID_INPUT_PICTURE_0)
712
        avcenc_context.current_input_surface = SID_INPUT_PICTURE_1;
713
    else
714
        avcenc_context.current_input_surface = SID_INPUT_PICTURE_0;
715
 
716
    if (is_idr) {
717
        VAEncPackedHeaderParameterBuffer packed_header_param_buffer;
718
        unsigned int length_in_bits, offset_in_bytes;
719
        unsigned char *packed_seq_buffer = NULL, *packed_pic_buffer = NULL;
720
 
721
        assert(slice_type == SLICE_TYPE_I);
722
        length_in_bits = build_packed_seq_buffer(&packed_seq_buffer);
723
        offset_in_bytes = 0;
724
        packed_header_param_buffer.type = VAEncPackedHeaderSequence;
725
        packed_header_param_buffer.bit_length = length_in_bits;
726
        packed_header_param_buffer.has_emulation_bytes = 0;
727
        va_status = vaCreateBuffer(va_dpy,
728
                                   avcenc_context.context_id,
729
                                   VAEncPackedHeaderParameterBufferType,
730
                                   sizeof(packed_header_param_buffer), 1, &packed_header_param_buffer,
731
                                   &avcenc_context.packed_seq_header_param_buf_id);
732
        CHECK_VASTATUS(va_status,"vaCreateBuffer");
733
 
734
        va_status = vaCreateBuffer(va_dpy,
735
                                   avcenc_context.context_id,
736
                                   VAEncPackedHeaderDataBufferType,
737
                                   (length_in_bits + 7) / 8, 1, packed_seq_buffer,
738
                                   &avcenc_context.packed_seq_buf_id);
739
        CHECK_VASTATUS(va_status,"vaCreateBuffer");
740
 
741
        length_in_bits = build_packed_pic_buffer(&packed_pic_buffer);
742
        offset_in_bytes = 0;
743
        packed_header_param_buffer.type = VAEncPackedHeaderPicture;
744
        packed_header_param_buffer.bit_length = length_in_bits;
745
        packed_header_param_buffer.has_emulation_bytes = 0;
746
 
747
        va_status = vaCreateBuffer(va_dpy,
748
                                   avcenc_context.context_id,
749
                                   VAEncPackedHeaderParameterBufferType,
750
                                   sizeof(packed_header_param_buffer), 1, &packed_header_param_buffer,
751
                                   &avcenc_context.packed_pic_header_param_buf_id);
752
        CHECK_VASTATUS(va_status,"vaCreateBuffer");
753
 
754
        va_status = vaCreateBuffer(va_dpy,
755
                                   avcenc_context.context_id,
756
                                   VAEncPackedHeaderDataBufferType,
757
                                   (length_in_bits + 7) / 8, 1, packed_pic_buffer,
758
                                   &avcenc_context.packed_pic_buf_id);
759
        CHECK_VASTATUS(va_status,"vaCreateBuffer");
760
 
761
        free(packed_seq_buffer);
762
        free(packed_pic_buffer);
763
    }
764
 
765
    /* sequence parameter set */
766
    VAEncSequenceParameterBufferH264 *seq_param = &avcenc_context.seq_param;
767
    va_status = vaCreateBuffer(va_dpy,
768
                               avcenc_context.context_id,
769
                               VAEncSequenceParameterBufferType,
770
                               sizeof(*seq_param), 1, seq_param,
771
                               &avcenc_context.seq_param_buf_id);
772
    CHECK_VASTATUS(va_status,"vaCreateBuffer");
773
 
774
 
775
    /* hrd parameter */
776
    VAEncMiscParameterBuffer *misc_param;
777
    VAEncMiscParameterHRD *misc_hrd_param;
778
    vaCreateBuffer(va_dpy,
779
                   avcenc_context.context_id,
780
                   VAEncMiscParameterBufferType,
781
                   sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterRateControl),
782
                   1,
783
                   NULL,
784
                   &avcenc_context.misc_parameter_hrd_buf_id);
785
    CHECK_VASTATUS(va_status, "vaCreateBuffer");
786
 
787
    vaMapBuffer(va_dpy,
788
                avcenc_context.misc_parameter_hrd_buf_id,
789
                (void **)&misc_param);
790
    misc_param->type = VAEncMiscParameterTypeHRD;
791
    misc_hrd_param = (VAEncMiscParameterHRD *)misc_param->data;
792
 
793
    if (frame_bit_rate > 0) {
794
        misc_hrd_param->initial_buffer_fullness = frame_bit_rate * 1000 * 4;
795
        misc_hrd_param->buffer_size = frame_bit_rate * 1000 * 8;
796
    } else {
797
        misc_hrd_param->initial_buffer_fullness = 0;
798
        misc_hrd_param->buffer_size = 0;
799
    }
800
 
801
    vaUnmapBuffer(va_dpy, avcenc_context.misc_parameter_hrd_buf_id);
802
 
803
    return 0;
804
}
805
 
806
int avcenc_render_picture()
807
{
808
    VAStatus va_status;
809
    VABufferID va_buffers[10];
810
    unsigned int num_va_buffers = 0;
811
    int i;
812
 
813
    va_buffers[num_va_buffers++] = avcenc_context.seq_param_buf_id;
814
    va_buffers[num_va_buffers++] = avcenc_context.pic_param_buf_id;
815
 
816
    if (avcenc_context.packed_seq_header_param_buf_id != VA_INVALID_ID)
817
        va_buffers[num_va_buffers++] = avcenc_context.packed_seq_header_param_buf_id;
818
 
819
    if (avcenc_context.packed_seq_buf_id != VA_INVALID_ID)
820
        va_buffers[num_va_buffers++] = avcenc_context.packed_seq_buf_id;
821
 
822
    if (avcenc_context.packed_pic_header_param_buf_id != VA_INVALID_ID)
823
        va_buffers[num_va_buffers++] = avcenc_context.packed_pic_header_param_buf_id;
824
 
825
    if (avcenc_context.packed_pic_buf_id != VA_INVALID_ID)
826
        va_buffers[num_va_buffers++] = avcenc_context.packed_pic_buf_id;
827
 
828
    if (avcenc_context.packed_sei_header_param_buf_id != VA_INVALID_ID)
829
        va_buffers[num_va_buffers++] = avcenc_context.packed_sei_header_param_buf_id;
830
 
831
    if (avcenc_context.packed_sei_buf_id != VA_INVALID_ID)
832
        va_buffers[num_va_buffers++] = avcenc_context.packed_sei_buf_id;
833
 
834
    if (avcenc_context.misc_parameter_hrd_buf_id != VA_INVALID_ID)
835
        va_buffers[num_va_buffers++] =  avcenc_context.misc_parameter_hrd_buf_id;
836
 
837
    va_status = vaBeginPicture(va_dpy,
838
                               avcenc_context.context_id,
839
                               surface_ids[avcenc_context.current_input_surface]);
840
    CHECK_VASTATUS(va_status,"vaBeginPicture");
841
 
842
    va_status = vaRenderPicture(va_dpy,
843
                                avcenc_context.context_id,
844
                                va_buffers,
845
                                num_va_buffers);
846
    CHECK_VASTATUS(va_status,"vaRenderPicture");
847
 
848
    for(i = 0; i < avcenc_context.num_slices; i++) {
849
        va_status = vaRenderPicture(va_dpy,
850
                                avcenc_context.context_id,
851
                                &avcenc_context.slice_param_buf_id[i],
852
                                1);
853
        CHECK_VASTATUS(va_status,"vaRenderPicture");
854
    }
855
 
856
    va_status = vaEndPicture(va_dpy, avcenc_context.context_id);
857
    CHECK_VASTATUS(va_status,"vaEndPicture");
858
 
859
    return 0;
860
}
861
 
862
static int avcenc_destroy_buffers(VABufferID *va_buffers, unsigned int num_va_buffers)
863
{
864
    VAStatus va_status;
865
    unsigned int i;
866
 
867
    for (i = 0; i < num_va_buffers; i++) {
868
        if (va_buffers[i] != VA_INVALID_ID) {
869
            va_status = vaDestroyBuffer(va_dpy, va_buffers[i]);
870
            CHECK_VASTATUS(va_status,"vaDestroyBuffer");
871
            va_buffers[i] = VA_INVALID_ID;
872
        }
873
    }
874
 
875
    return 0;
876
}
877
 
878
static void end_picture()
879
{
880
 
881
    update_ReferenceFrames();
882
    avcenc_destroy_buffers(&avcenc_context.seq_param_buf_id, 1);
883
    avcenc_destroy_buffers(&avcenc_context.pic_param_buf_id, 1);
884
    avcenc_destroy_buffers(&avcenc_context.packed_seq_header_param_buf_id, 1);
885
    avcenc_destroy_buffers(&avcenc_context.packed_seq_buf_id, 1);
886
    avcenc_destroy_buffers(&avcenc_context.packed_pic_header_param_buf_id, 1);
887
    avcenc_destroy_buffers(&avcenc_context.packed_pic_buf_id, 1);
888
    avcenc_destroy_buffers(&avcenc_context.packed_sei_header_param_buf_id, 1);
889
    avcenc_destroy_buffers(&avcenc_context.packed_sei_buf_id, 1);
890
    avcenc_destroy_buffers(&avcenc_context.slice_param_buf_id[0], avcenc_context.num_slices);
891
    avcenc_destroy_buffers(&avcenc_context.codedbuf_buf_id, 1);
892
    avcenc_destroy_buffers(&avcenc_context.misc_parameter_hrd_buf_id, 1);
893
 
894
    memset(avcenc_context.slice_param, 0, sizeof(avcenc_context.slice_param));
895
    avcenc_context.num_slices = 0;
896
}
897
 
898
#define BITSTREAM_ALLOCATE_STEPPING     4096
899
 
900
struct __bitstream {
901
    unsigned int *buffer;
902
    int bit_offset;
903
    int max_size_in_dword;
904
};
905
 
906
typedef struct __bitstream bitstream;
907
 
908
#if 0
909
static int
910
get_coded_bitsteam_length(unsigned char *buffer, int buffer_length)
911
{
912
    int i;
913
 
914
    for (i = 0; i < buffer_length - 3; i++) {
915
        if (!buffer[i] &&
916
            !buffer[i + 1] &&
917
            !buffer[i + 2] &&
918
            !buffer[i + 3])
919
            break;
920
    }
921
 
922
    return i;
923
}
924
#endif
925
 
926
static unsigned int
927
va_swap32(unsigned int val)
928
{
929
    unsigned char *pval = (unsigned char *)&val;
930
 
931
    return ((pval[0] << 24)     |
932
            (pval[1] << 16)     |
933
            (pval[2] << 8)      |
934
            (pval[3] << 0));
935
}
936
 
937
static void
938
bitstream_start(bitstream *bs)
939
{
940
    bs->max_size_in_dword = BITSTREAM_ALLOCATE_STEPPING;
941
    bs->buffer = calloc(bs->max_size_in_dword * sizeof(int), 1);
942
    bs->bit_offset = 0;
943
}
944
 
945
static void
946
bitstream_end(bitstream *bs)
947
{
948
    int pos = (bs->bit_offset >> 5);
949
    int bit_offset = (bs->bit_offset & 0x1f);
950
    int bit_left = 32 - bit_offset;
951
 
952
    if (bit_offset) {
953
        bs->buffer[pos] = va_swap32((bs->buffer[pos] << bit_left));
954
    }
955
}
956
 
957
static void
958
bitstream_put_ui(bitstream *bs, unsigned int val, int size_in_bits)
959
{
960
    int pos = (bs->bit_offset >> 5);
961
    int bit_offset = (bs->bit_offset & 0x1f);
962
    int bit_left = 32 - bit_offset;
963
 
964
    if (!size_in_bits)
965
        return;
966
 
967
    bs->bit_offset += size_in_bits;
968
 
969
    if (bit_left > size_in_bits) {
970
        bs->buffer[pos] = (bs->buffer[pos] << size_in_bits | val);
971
    } else {
972
        size_in_bits -= bit_left;
973
        bs->buffer[pos] = (bs->buffer[pos] << bit_left) | (val >> size_in_bits);
974
        bs->buffer[pos] = va_swap32(bs->buffer[pos]);
975
 
976
        if (pos + 1 == bs->max_size_in_dword) {
977
            bs->max_size_in_dword += BITSTREAM_ALLOCATE_STEPPING;
978
            bs->buffer = realloc(bs->buffer, bs->max_size_in_dword * sizeof(unsigned int));
979
        }
980
 
981
        bs->buffer[pos + 1] = val;
982
    }
983
}
984
 
985
static void
986
bitstream_put_ue(bitstream *bs, unsigned int val)
987
{
988
    int size_in_bits = 0;
989
    int tmp_val = ++val;
990
 
991
    while (tmp_val) {
992
        tmp_val >>= 1;
993
        size_in_bits++;
994
    }
995
 
996
    bitstream_put_ui(bs, 0, size_in_bits - 1); // leading zero
997
    bitstream_put_ui(bs, val, size_in_bits);
998
}
999
 
1000
static void
1001
bitstream_put_se(bitstream *bs, int val)
1002
{
1003
    unsigned int new_val;
1004
 
1005
    if (val <= 0)
1006
        new_val = -2 * val;
1007
    else
1008
        new_val = 2 * val - 1;
1009
 
1010
    bitstream_put_ue(bs, new_val);
1011
}
1012
 
1013
static void
1014
bitstream_byte_aligning(bitstream *bs, int bit)
1015
{
1016
    int bit_offset = (bs->bit_offset & 0x7);
1017
    int bit_left = 8 - bit_offset;
1018
    int new_val;
1019
 
1020
    if (!bit_offset)
1021
        return;
1022
 
1023
    assert(bit == 0 || bit == 1);
1024
 
1025
    if (bit)
1026
        new_val = (1 << bit_left) - 1;
1027
    else
1028
        new_val = 0;
1029
 
1030
    bitstream_put_ui(bs, new_val, bit_left);
1031
}
1032
 
1033
static void
1034
rbsp_trailing_bits(bitstream *bs)
1035
{
1036
    bitstream_put_ui(bs, 1, 1);
1037
    bitstream_byte_aligning(bs, 0);
1038
}
1039
 
1040
static void nal_start_code_prefix(bitstream *bs)
1041
{
1042
    bitstream_put_ui(bs, 0x00000001, 32);
1043
}
1044
 
1045
static void nal_header(bitstream *bs, int nal_ref_idc, int nal_unit_type)
1046
{
1047
    bitstream_put_ui(bs, 0, 1);                /* forbidden_zero_bit: 0 */
1048
    bitstream_put_ui(bs, nal_ref_idc, 2);
1049
    bitstream_put_ui(bs, nal_unit_type, 5);
1050
}
1051
 
1052
static void sps_rbsp(bitstream *bs)
1053
{
1054
    VAEncSequenceParameterBufferH264 *seq_param = &avcenc_context.seq_param;
1055
    int profile_idc = PROFILE_IDC_BASELINE;
1056
 
1057
    if (avcenc_context.profile == VAProfileH264High)
1058
        profile_idc = PROFILE_IDC_HIGH;
1059
    else if (avcenc_context.profile == VAProfileH264Main)
1060
        profile_idc = PROFILE_IDC_MAIN;
1061
 
1062
    bitstream_put_ui(bs, profile_idc, 8);               /* profile_idc */
1063
    bitstream_put_ui(bs, !!(avcenc_context.constraint_set_flag & 1), 1);                         /* constraint_set0_flag */
1064
    bitstream_put_ui(bs, !!(avcenc_context.constraint_set_flag & 2), 1);                         /* constraint_set1_flag */
1065
    bitstream_put_ui(bs, !!(avcenc_context.constraint_set_flag & 4), 1);                         /* constraint_set2_flag */
1066
    bitstream_put_ui(bs, !!(avcenc_context.constraint_set_flag & 8), 1);                         /* constraint_set3_flag */
1067
    bitstream_put_ui(bs, 0, 4);                         /* reserved_zero_4bits */
1068
    bitstream_put_ui(bs, seq_param->level_idc, 8);      /* level_idc */
1069
    bitstream_put_ue(bs, seq_param->seq_parameter_set_id);      /* seq_parameter_set_id */
1070
 
1071
    if ( profile_idc == PROFILE_IDC_HIGH) {
1072
        bitstream_put_ue(bs, 1);        /* chroma_format_idc = 1, 4:2:0 */
1073
        bitstream_put_ue(bs, 0);        /* bit_depth_luma_minus8 */
1074
        bitstream_put_ue(bs, 0);        /* bit_depth_chroma_minus8 */
1075
        bitstream_put_ui(bs, 0, 1);     /* qpprime_y_zero_transform_bypass_flag */
1076
        bitstream_put_ui(bs, 0, 1);     /* seq_scaling_matrix_present_flag */
1077
    }
1078
 
1079
    bitstream_put_ue(bs, seq_param->seq_fields.bits.log2_max_frame_num_minus4); /* log2_max_frame_num_minus4 */
1080
    bitstream_put_ue(bs, seq_param->seq_fields.bits.pic_order_cnt_type);        /* pic_order_cnt_type */
1081
 
1082
    if (seq_param->seq_fields.bits.pic_order_cnt_type == 0)
1083
        bitstream_put_ue(bs, seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4);     /* log2_max_pic_order_cnt_lsb_minus4 */
1084
    else {
1085
        assert(0);
1086
    }
1087
 
1088
    bitstream_put_ue(bs, seq_param->max_num_ref_frames);        /* num_ref_frames */
1089
    bitstream_put_ui(bs, 0, 1);                                 /* gaps_in_frame_num_value_allowed_flag */
1090
 
1091
    bitstream_put_ue(bs, seq_param->picture_width_in_mbs - 1);  /* pic_width_in_mbs_minus1 */
1092
    bitstream_put_ue(bs, seq_param->picture_height_in_mbs - 1); /* pic_height_in_map_units_minus1 */
1093
    bitstream_put_ui(bs, seq_param->seq_fields.bits.frame_mbs_only_flag, 1);    /* frame_mbs_only_flag */
1094
 
1095
    if (!seq_param->seq_fields.bits.frame_mbs_only_flag) {
1096
        assert(0);
1097
    }
1098
 
1099
    bitstream_put_ui(bs, seq_param->seq_fields.bits.direct_8x8_inference_flag, 1);      /* direct_8x8_inference_flag */
1100
    bitstream_put_ui(bs, seq_param->frame_cropping_flag, 1);            /* frame_cropping_flag */
1101
 
1102
    if (seq_param->frame_cropping_flag) {
1103
        bitstream_put_ue(bs, seq_param->frame_crop_left_offset);        /* frame_crop_left_offset */
1104
        bitstream_put_ue(bs, seq_param->frame_crop_right_offset);       /* frame_crop_right_offset */
1105
        bitstream_put_ue(bs, seq_param->frame_crop_top_offset);         /* frame_crop_top_offset */
1106
        bitstream_put_ue(bs, seq_param->frame_crop_bottom_offset);      /* frame_crop_bottom_offset */
1107
    }
1108
 
1109
    if ( frame_bit_rate < 0 ) {
1110
        bitstream_put_ui(bs, 0, 1); /* vui_parameters_present_flag */
1111
    } else {
1112
        bitstream_put_ui(bs, 1, 1); /* vui_parameters_present_flag */
1113
        bitstream_put_ui(bs, 0, 1); /* aspect_ratio_info_present_flag */
1114
        bitstream_put_ui(bs, 0, 1); /* overscan_info_present_flag */
1115
        bitstream_put_ui(bs, 0, 1); /* video_signal_type_present_flag */
1116
        bitstream_put_ui(bs, 0, 1); /* chroma_loc_info_present_flag */
1117
        bitstream_put_ui(bs, 1, 1); /* timing_info_present_flag */
1118
        {
1119
            bitstream_put_ui(bs, 1, 32);
1120
            bitstream_put_ui(bs, frame_rate * 2, 32);
1121
            bitstream_put_ui(bs, 1, 1);
1122
        }
1123
        bitstream_put_ui(bs, 1, 1); /* nal_hrd_parameters_present_flag */
1124
        {
1125
            // hrd_parameters
1126
            bitstream_put_ue(bs, 0);    /* cpb_cnt_minus1 */
1127
            bitstream_put_ui(bs, 0, 4); /* bit_rate_scale */
1128
            bitstream_put_ui(bs, 2, 4); /* cpb_size_scale */
1129
 
1130
	    /* the frame_bit_rate is in kbps */
1131
            bitstream_put_ue(bs, (((frame_bit_rate * 1000)>> 6) - 1)); /* bit_rate_value_minus1[0] */
1132
            bitstream_put_ue(bs, ((frame_bit_rate * 8000) >> 6) - 1); /* cpb_size_value_minus1[0] */
1133
            bitstream_put_ui(bs, 1, 1);  /* cbr_flag[0] */
1134
 
1135
            /* initial_cpb_removal_delay_length_minus1 */
1136
            bitstream_put_ui(bs,
1137
                (avcenc_context.i_initial_cpb_removal_delay_length - 1), 5);
1138
            /* cpb_removal_delay_length_minus1 */
1139
            bitstream_put_ui(bs,
1140
                (avcenc_context.i_cpb_removal_delay_length - 1), 5);
1141
            /* dpb_output_delay_length_minus1 */
1142
            bitstream_put_ui(bs,
1143
                (avcenc_context.i_dpb_output_delay_length - 1), 5);
1144
            /* time_offset_length  */
1145
            bitstream_put_ui(bs,
1146
                (avcenc_context.time_offset_length - 1), 5);
1147
        }
1148
        bitstream_put_ui(bs, 0, 1);   /* vcl_hrd_parameters_present_flag */
1149
        bitstream_put_ui(bs, 0, 1);   /* low_delay_hrd_flag */
1150
 
1151
        bitstream_put_ui(bs, 0, 1); /* pic_struct_present_flag */
1152
        bitstream_put_ui(bs, 0, 1); /* bitstream_restriction_flag */
1153
    }
1154
 
1155
    rbsp_trailing_bits(bs);     /* rbsp_trailing_bits */
1156
}
1157
 
1158
#if 0
1159
static void build_nal_sps(FILE *avc_fp)
1160
{
1161
    bitstream bs;
1162
 
1163
    bitstream_start(&bs);
1164
    nal_start_code_prefix(&bs);
1165
    nal_header(&bs, NAL_REF_IDC_HIGH, NAL_SPS);
1166
    sps_rbsp(&bs);
1167
    bitstream_end(&bs, avc_fp);
1168
}
1169
#endif
1170
 
1171
static void pps_rbsp(bitstream *bs)
1172
{
1173
    VAEncPictureParameterBufferH264 *pic_param = &avcenc_context.pic_param;
1174
 
1175
    bitstream_put_ue(bs, pic_param->pic_parameter_set_id);      /* pic_parameter_set_id */
1176
    bitstream_put_ue(bs, pic_param->seq_parameter_set_id);      /* seq_parameter_set_id */
1177
 
1178
    bitstream_put_ui(bs, pic_param->pic_fields.bits.entropy_coding_mode_flag, 1);  /* entropy_coding_mode_flag */
1179
 
1180
    bitstream_put_ui(bs, 0, 1);                         /* pic_order_present_flag: 0 */
1181
 
1182
    bitstream_put_ue(bs, 0);                            /* num_slice_groups_minus1 */
1183
 
1184
    bitstream_put_ue(bs, pic_param->num_ref_idx_l0_active_minus1);      /* num_ref_idx_l0_active_minus1 */
1185
    bitstream_put_ue(bs, pic_param->num_ref_idx_l1_active_minus1);      /* num_ref_idx_l1_active_minus1 1 */
1186
 
1187
    bitstream_put_ui(bs, pic_param->pic_fields.bits.weighted_pred_flag, 1);     /* weighted_pred_flag: 0 */
1188
    bitstream_put_ui(bs, pic_param->pic_fields.bits.weighted_bipred_idc, 2);	/* weighted_bipred_idc: 0 */
1189
 
1190
    bitstream_put_se(bs, pic_param->pic_init_qp - 26);  /* pic_init_qp_minus26 */
1191
    bitstream_put_se(bs, 0);                            /* pic_init_qs_minus26 */
1192
    bitstream_put_se(bs, 0);                            /* chroma_qp_index_offset */
1193
 
1194
    bitstream_put_ui(bs, pic_param->pic_fields.bits.deblocking_filter_control_present_flag, 1); /* deblocking_filter_control_present_flag */
1195
    bitstream_put_ui(bs, 0, 1);                         /* constrained_intra_pred_flag */
1196
    bitstream_put_ui(bs, 0, 1);                         /* redundant_pic_cnt_present_flag */
1197
 
1198
    /* more_rbsp_data */
1199
    bitstream_put_ui(bs, pic_param->pic_fields.bits.transform_8x8_mode_flag, 1);    /*transform_8x8_mode_flag */
1200
    bitstream_put_ui(bs, 0, 1);                         /* pic_scaling_matrix_present_flag */
1201
    bitstream_put_se(bs, pic_param->second_chroma_qp_index_offset );    /*second_chroma_qp_index_offset */
1202
 
1203
    rbsp_trailing_bits(bs);
1204
}
1205
 
1206
#if 0
1207
static void build_nal_pps(FILE *avc_fp)
1208
{
1209
    bitstream bs;
1210
 
1211
    bitstream_start(&bs);
1212
    nal_start_code_prefix(&bs);
1213
    nal_header(&bs, NAL_REF_IDC_HIGH, NAL_PPS);
1214
    pps_rbsp(&bs);
1215
    bitstream_end(&bs, avc_fp);
1216
}
1217
 
1218
static void
1219
build_header(FILE *avc_fp)
1220
{
1221
    build_nal_sps(avc_fp);
1222
    build_nal_pps(avc_fp);
1223
}
1224
#endif
1225
 
1226
static int
1227
build_packed_pic_buffer(unsigned char **header_buffer)
1228
{
1229
    bitstream bs;
1230
 
1231
    bitstream_start(&bs);
1232
    nal_start_code_prefix(&bs);
1233
    nal_header(&bs, NAL_REF_IDC_HIGH, NAL_PPS);
1234
    pps_rbsp(&bs);
1235
    bitstream_end(&bs);
1236
 
1237
    *header_buffer = (unsigned char *)bs.buffer;
1238
    return bs.bit_offset;
1239
}
1240
 
1241
static int
1242
build_packed_seq_buffer(unsigned char **header_buffer)
1243
{
1244
    bitstream bs;
1245
 
1246
    bitstream_start(&bs);
1247
    nal_start_code_prefix(&bs);
1248
    nal_header(&bs, NAL_REF_IDC_HIGH, NAL_SPS);
1249
    sps_rbsp(&bs);
1250
    bitstream_end(&bs);
1251
 
1252
    *header_buffer = (unsigned char *)bs.buffer;
1253
    return bs.bit_offset;
1254
}
1255
 
1256
static int
1257
build_packed_idr_sei_buffer_timing(unsigned int init_cpb_removal_delay_length,
1258
				unsigned int cpb_removal_length,
1259
				unsigned int dpb_output_length,
1260
				unsigned char **sei_buffer)
1261
{
1262
    unsigned char *byte_buf;
1263
    int bp_byte_size, i, pic_byte_size;
1264
    unsigned int cpb_removal_delay;
1265
 
1266
    bitstream nal_bs;
1267
    bitstream sei_bp_bs, sei_pic_bs;
1268
 
1269
    bitstream_start(&sei_bp_bs);
1270
    bitstream_put_ue(&sei_bp_bs, 0);       /*seq_parameter_set_id*/
1271
    /* SEI buffer period info */
1272
    /* NALHrdBpPresentFlag == 1 */
1273
    bitstream_put_ui(&sei_bp_bs, avcenc_context.i_initial_cpb_removal_delay,
1274
                     init_cpb_removal_delay_length);
1275
    bitstream_put_ui(&sei_bp_bs, avcenc_context.i_initial_cpb_removal_delay_offset,
1276
                     init_cpb_removal_delay_length);
1277
    if ( sei_bp_bs.bit_offset & 0x7) {
1278
        bitstream_put_ui(&sei_bp_bs, 1, 1);
1279
    }
1280
    bitstream_end(&sei_bp_bs);
1281
    bp_byte_size = (sei_bp_bs.bit_offset + 7) / 8;
1282
 
1283
    /* SEI pic timing info */
1284
    bitstream_start(&sei_pic_bs);
1285
    /* The info of CPB and DPB delay is controlled by CpbDpbDelaysPresentFlag,
1286
     * which is derived as 1 if one of the following conditions is true:
1287
     * nal_hrd_parameters_present_flag is present in the bitstream and is equal to 1,
1288
     * vcl_hrd_parameters_present_flag is present in the bitstream and is equal to 1,
1289
     */
1290
    cpb_removal_delay = (avcenc_context.current_cpb_removal - avcenc_context.prev_idr_cpb_removal);
1291
    bitstream_put_ui(&sei_pic_bs, cpb_removal_delay, cpb_removal_length);
1292
    bitstream_put_ui(&sei_pic_bs, avcenc_context.current_dpb_removal_delta,
1293
                     dpb_output_length);
1294
    if ( sei_pic_bs.bit_offset & 0x7) {
1295
        bitstream_put_ui(&sei_pic_bs, 1, 1);
1296
    }
1297
    /* The pic_structure_present_flag determines whether the pic_structure
1298
     * info is written into the SEI pic timing info.
1299
     * Currently it is set to zero.
1300
     */
1301
    bitstream_end(&sei_pic_bs);
1302
    pic_byte_size = (sei_pic_bs.bit_offset + 7) / 8;
1303
 
1304
    bitstream_start(&nal_bs);
1305
    nal_start_code_prefix(&nal_bs);
1306
    nal_header(&nal_bs, NAL_REF_IDC_NONE, NAL_SEI);
1307
 
1308
	/* Write the SEI buffer period data */
1309
    bitstream_put_ui(&nal_bs, 0, 8);
1310
    bitstream_put_ui(&nal_bs, bp_byte_size, 8);
1311
 
1312
    byte_buf = (unsigned char *)sei_bp_bs.buffer;
1313
    for(i = 0; i < bp_byte_size; i++) {
1314
        bitstream_put_ui(&nal_bs, byte_buf[i], 8);
1315
    }
1316
    free(byte_buf);
1317
	/* write the SEI pic timing data */
1318
    bitstream_put_ui(&nal_bs, 0x01, 8);
1319
    bitstream_put_ui(&nal_bs, pic_byte_size, 8);
1320
 
1321
    byte_buf = (unsigned char *)sei_pic_bs.buffer;
1322
    for(i = 0; i < pic_byte_size; i++) {
1323
        bitstream_put_ui(&nal_bs, byte_buf[i], 8);
1324
    }
1325
    free(byte_buf);
1326
 
1327
    rbsp_trailing_bits(&nal_bs);
1328
    bitstream_end(&nal_bs);
1329
 
1330
    *sei_buffer = (unsigned char *)nal_bs.buffer;
1331
 
1332
    return nal_bs.bit_offset;
1333
}
1334
 
1335
static int
1336
build_packed_sei_pic_timing(unsigned int cpb_removal_length,
1337
				unsigned int dpb_output_length,
1338
				unsigned char **sei_buffer)
1339
{
1340
    unsigned char *byte_buf;
1341
    int i, pic_byte_size;
1342
    unsigned int cpb_removal_delay;
1343
 
1344
    bitstream nal_bs;
1345
    bitstream sei_pic_bs;
1346
 
1347
    bitstream_start(&sei_pic_bs);
1348
    /* The info of CPB and DPB delay is controlled by CpbDpbDelaysPresentFlag,
1349
     * which is derived as 1 if one of the following conditions is true:
1350
     * nal_hrd_parameters_present_flag is present in the bitstream and is equal to 1,
1351
     * vcl_hrd_parameters_present_flag is present in the bitstream and is equal to 1,
1352
     */
1353
    cpb_removal_delay = (avcenc_context.current_cpb_removal - avcenc_context.current_idr_cpb_removal);
1354
    bitstream_put_ui(&sei_pic_bs, cpb_removal_delay, cpb_removal_length);
1355
    bitstream_put_ui(&sei_pic_bs, avcenc_context.current_dpb_removal_delta,
1356
                     dpb_output_length);
1357
    if ( sei_pic_bs.bit_offset & 0x7) {
1358
        bitstream_put_ui(&sei_pic_bs, 1, 1);
1359
    }
1360
 
1361
    /* The pic_structure_present_flag determines whether the pic_structure
1362
     * info is written into the SEI pic timing info.
1363
     * Currently it is set to zero.
1364
     */
1365
    bitstream_end(&sei_pic_bs);
1366
    pic_byte_size = (sei_pic_bs.bit_offset + 7) / 8;
1367
 
1368
    bitstream_start(&nal_bs);
1369
    nal_start_code_prefix(&nal_bs);
1370
    nal_header(&nal_bs, NAL_REF_IDC_NONE, NAL_SEI);
1371
 
1372
	/* write the SEI Pic timing data */
1373
    bitstream_put_ui(&nal_bs, 0x01, 8);
1374
    bitstream_put_ui(&nal_bs, pic_byte_size, 8);
1375
 
1376
    byte_buf = (unsigned char *)sei_pic_bs.buffer;
1377
    for(i = 0; i < pic_byte_size; i++) {
1378
        bitstream_put_ui(&nal_bs, byte_buf[i], 8);
1379
    }
1380
    free(byte_buf);
1381
 
1382
    rbsp_trailing_bits(&nal_bs);
1383
    bitstream_end(&nal_bs);
1384
 
1385
    *sei_buffer = (unsigned char *)nal_bs.buffer;
1386
 
1387
    return nal_bs.bit_offset;
1388
}
1389
 
1390
#if 0
1391
static void
1392
slice_header(bitstream *bs, int frame_num, int display_frame, int slice_type, int nal_ref_idc, int is_idr)
1393
{
1394
    VAEncSequenceParameterBufferH264 *seq_param = &avcenc_context.seq_param;
1395
    VAEncPictureParameterBufferH264 *pic_param = &avcenc_context.pic_param;
1396
    int is_cabac = (pic_param->pic_fields.bits.entropy_coding_mode_flag == ENTROPY_MODE_CABAC);
1397
 
1398
    bitstream_put_ue(bs, 0);                   /* first_mb_in_slice: 0 */
1399
    bitstream_put_ue(bs, slice_type);          /* slice_type */
1400
    bitstream_put_ue(bs, 0);                   /* pic_parameter_set_id: 0 */
1401
    bitstream_put_ui(bs, frame_num & 0x0F, seq_param->seq_fields.bits.log2_max_frame_num_minus4 + 4);    /* frame_num */
1402
 
1403
    /* frame_mbs_only_flag == 1 */
1404
    if (!seq_param->seq_fields.bits.frame_mbs_only_flag) {
1405
        /* FIXME: */
1406
        assert(0);
1407
    }
1408
 
1409
    if (is_idr)
1410
        bitstream_put_ue(bs, 0);		/* idr_pic_id: 0 */
1411
 
1412
    if (seq_param->seq_fields.bits.pic_order_cnt_type == 0) {
1413
        bitstream_put_ui(bs, (display_frame*2) & 0x3F, seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 + 4);
1414
        /* only support frame */
1415
    } else {
1416
        /* FIXME: */
1417
        assert(0);
1418
    }
1419
 
1420
    /* redundant_pic_cnt_present_flag == 0 */
1421
 
1422
    /* slice type */
1423
    if (slice_type == SLICE_TYPE_P) {
1424
        bitstream_put_ui(bs, 0, 1);            /* num_ref_idx_active_override_flag: 0 */
1425
        /* ref_pic_list_reordering */
1426
        bitstream_put_ui(bs, 0, 1);            /* ref_pic_list_reordering_flag_l0: 0 */
1427
    } else if (slice_type == SLICE_TYPE_B) {
1428
        bitstream_put_ui(bs, 1, 1);            /* direct_spatial_mv_pred: 1 */
1429
        bitstream_put_ui(bs, 0, 1);            /* num_ref_idx_active_override_flag: 0 */
1430
        /* ref_pic_list_reordering */
1431
        bitstream_put_ui(bs, 0, 1);            /* ref_pic_list_reordering_flag_l0: 0 */
1432
        bitstream_put_ui(bs, 0, 1);            /* ref_pic_list_reordering_flag_l1: 0 */
1433
    }
1434
 
1435
    /* weighted_pred_flag == 0 */
1436
 
1437
    /* dec_ref_pic_marking */
1438
    if (nal_ref_idc != 0) {
1439
        if ( is_idr) {
1440
            bitstream_put_ui(bs, 0, 1);            /* no_output_of_prior_pics_flag: 0 */
1441
            bitstream_put_ui(bs, 0, 1);            /* long_term_reference_flag: 0 */
1442
        } else {
1443
            bitstream_put_ui(bs, 0, 1);            /* adaptive_ref_pic_marking_mode_flag: 0 */
1444
        }
1445
    }
1446
 
1447
    if (is_cabac && (slice_type != SLICE_TYPE_I))
1448
        bitstream_put_ue(bs, 0);               /* cabac_init_idc: 0 */
1449
 
1450
    bitstream_put_se(bs, 0);                   /* slice_qp_delta: 0 */
1451
 
1452
    if (pic_param->pic_fields.bits.deblocking_filter_control_present_flag == 1) {
1453
        bitstream_put_ue(bs, 0);               /* disable_deblocking_filter_idc: 0 */
1454
        bitstream_put_se(bs, 2);               /* slice_alpha_c0_offset_div2: 2 */
1455
        bitstream_put_se(bs, 2);               /* slice_beta_offset_div2: 2 */
1456
    }
1457
}
1458
 
1459
static void
1460
slice_data(bitstream *bs)
1461
{
1462
    VACodedBufferSegment *coded_buffer_segment;
1463
    unsigned char *coded_mem;
1464
    int i, slice_data_length;
1465
    VAStatus va_status;
1466
    VASurfaceStatus surface_status;
1467
 
1468
    va_status = vaSyncSurface(va_dpy, surface_ids[avcenc_context.current_input_surface]);
1469
    CHECK_VASTATUS(va_status,"vaSyncSurface");
1470
 
1471
    surface_status = 0;
1472
    va_status = vaQuerySurfaceStatus(va_dpy, surface_ids[avcenc_context.current_input_surface], &surface_status);
1473
    CHECK_VASTATUS(va_status,"vaQuerySurfaceStatus");
1474
 
1475
    va_status = vaMapBuffer(va_dpy, avcenc_context.codedbuf_buf_id, (void **)(&coded_buffer_segment));
1476
    CHECK_VASTATUS(va_status,"vaMapBuffer");
1477
    coded_mem = coded_buffer_segment->buf;
1478
 
1479
    slice_data_length = get_coded_bitsteam_length(coded_mem, codedbuf_size);
1480
 
1481
    for (i = 0; i < slice_data_length; i++) {
1482
        bitstream_put_ui(bs, *coded_mem, 8);
1483
        coded_mem++;
1484
    }
1485
 
1486
    vaUnmapBuffer(va_dpy, avcenc_context.codedbuf_buf_id);
1487
}
1488
 
1489
static void
1490
build_nal_slice(FILE *avc_fp, int frame_num, int display_frame, int slice_type, int is_idr)
1491
{
1492
    bitstream bs;
1493
 
1494
    bitstream_start(&bs);
1495
    slice_data(&bs);
1496
    bitstream_end(&bs, avc_fp);
1497
}
1498
 
1499
#endif
1500
 
1501
static int
1502
store_coded_buffer(FILE *avc_fp, int slice_type)
1503
{
1504
    VACodedBufferSegment *coded_buffer_segment;
1505
    unsigned char *coded_mem;
1506
    int slice_data_length;
1507
    VAStatus va_status;
1508
    VASurfaceStatus surface_status;
1509
    size_t w_items;
1510
 
1511
    va_status = vaSyncSurface(va_dpy, surface_ids[avcenc_context.current_input_surface]);
1512
    CHECK_VASTATUS(va_status,"vaSyncSurface");
1513
 
1514
    surface_status = 0;
1515
    va_status = vaQuerySurfaceStatus(va_dpy, surface_ids[avcenc_context.current_input_surface], &surface_status);
1516
    CHECK_VASTATUS(va_status,"vaQuerySurfaceStatus");
1517
 
1518
    va_status = vaMapBuffer(va_dpy, avcenc_context.codedbuf_buf_id, (void **)(&coded_buffer_segment));
1519
    CHECK_VASTATUS(va_status,"vaMapBuffer");
1520
    coded_mem = coded_buffer_segment->buf;
1521
 
1522
    if (coded_buffer_segment->status & VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK) {
1523
        if (slice_type == SLICE_TYPE_I)
1524
            avcenc_context.codedbuf_i_size *= 2;
1525
        else
1526
            avcenc_context.codedbuf_pb_size *= 2;
1527
 
1528
        vaUnmapBuffer(va_dpy, avcenc_context.codedbuf_buf_id);
1529
        return -1;
1530
    }
1531
 
1532
    slice_data_length = coded_buffer_segment->size;
1533
 
1534
    do {
1535
        w_items = fwrite(coded_mem, slice_data_length, 1, avc_fp);
1536
    } while (w_items != 1);
1537
 
1538
    vaUnmapBuffer(va_dpy, avcenc_context.codedbuf_buf_id);
1539
 
1540
    return 0;
1541
}
1542
 
1543
/*
1544
 * It is from the h264encode.c but it simplifies something.
1545
 * For example: When one frame is encoded as I-frame under the scenario with
1546
 * P-B frames, it will be regarded as IDR frame(key-frame) and then new GOP is
1547
 * started. If the video clip is encoded as all I-frames, the first frame
1548
 * is regarded as IDR and the remaining is regarded as I-frame.
1549
 *
1550
 */
1551
 
1552
static void encoding2display_order(
1553
    unsigned long long encoding_order,int gop_size,
1554
    int ip_period,
1555
    unsigned long long *displaying_order,
1556
    int *frame_type)
1557
{
1558
    int encoding_order_gop = 0;
1559
 
1560
    /* When ip_period is 0, all are I/IDR frames */
1561
    if (ip_period == 0) { /* all are I/IDR frames */
1562
        if (encoding_order == 0)
1563
            *frame_type = FRAME_IDR;
1564
        else
1565
            *frame_type = SLICE_TYPE_I;
1566
 
1567
        *displaying_order = encoding_order;
1568
        return;
1569
    }
1570
 
1571
    /* new sequence like
1572
     * IDR PPPPP IDRPPPPP
1573
     * IDR (PBB)(PBB)(PBB)(PBB) IDR (PBB)(PBB)(PBB)(PBB)
1574
     */
1575
    encoding_order_gop = encoding_order % gop_size;
1576
 
1577
    if (encoding_order_gop == 0) { /* the first frame */
1578
        *frame_type = FRAME_IDR;
1579
        *displaying_order = encoding_order;
1580
    } else {
1581
        int gop_delta;
1582
 
1583
        gop_delta = 1;
1584
 
1585
        if ((ip_period != 1) && ((gop_size - 1) % ip_period)) {
1586
            int ipb_size;
1587
            ipb_size = (gop_size - 1) / ip_period * ip_period + 1;
1588
            if (encoding_order_gop >= ipb_size) {
1589
                gop_delta = ipb_size;
1590
                ip_period = gop_size - ipb_size;
1591
            }
1592
        }
1593
 
1594
        if (((encoding_order_gop - gop_delta) % ip_period) == 0) { /* P frames */
1595
            *frame_type = SLICE_TYPE_P;
1596
	    *displaying_order = encoding_order + ip_period - 1;
1597
        } else {
1598
	    *frame_type = SLICE_TYPE_B;
1599
	    *displaying_order = encoding_order - 1;
1600
        }
1601
    }
1602
}
1603
 
1604
 
1605
static void
1606
encode_picture(FILE *yuv_fp, FILE *avc_fp,
1607
               int frame_num, int display_num,
1608
               int is_idr,
1609
               int slice_type, int next_is_bpic,
1610
               int next_display_num)
1611
{
1612
    VAStatus va_status;
1613
    int ret = 0, codedbuf_size;
1614
 
1615
    begin_picture(yuv_fp, frame_num, display_num, slice_type, is_idr);
1616
 
1617
    //if (next_display_num < frame_number) {
1618
    if (1) {
1619
        int index;
1620
 
1621
        /* prepare for next frame */
1622
        if (avcenc_context.current_input_surface == SID_INPUT_PICTURE_0)
1623
            index = SID_INPUT_PICTURE_1;
1624
        else
1625
            index = SID_INPUT_PICTURE_0;
1626
        if ( next_display_num >= frame_number )
1627
            next_display_num = frame_number - 1;
1628
        fseek(yuv_fp, frame_size * next_display_num, SEEK_SET);
1629
 
1630
        avcenc_context.upload_thread_param.yuv_fp = yuv_fp;
1631
        avcenc_context.upload_thread_param.surface_id = surface_ids[index];
1632
 
1633
        avcenc_context.upload_thread_value = pthread_create(&avcenc_context.upload_thread_id,
1634
                                                            NULL,
1635
                                                            upload_thread_function,
1636
                                                            (void*)&avcenc_context.upload_thread_param);
1637
    }
1638
 
1639
    do {
1640
        avcenc_destroy_buffers(&avcenc_context.codedbuf_buf_id, 1);
1641
        avcenc_destroy_buffers(&avcenc_context.pic_param_buf_id, 1);
1642
 
1643
 
1644
        if (SLICE_TYPE_I == slice_type) {
1645
            codedbuf_size = avcenc_context.codedbuf_i_size;
1646
        } else {
1647
            codedbuf_size = avcenc_context.codedbuf_pb_size;
1648
        }
1649
 
1650
        /* coded buffer */
1651
        va_status = vaCreateBuffer(va_dpy,
1652
                                   avcenc_context.context_id,
1653
                                   VAEncCodedBufferType,
1654
                                   codedbuf_size, 1, NULL,
1655
                                   &avcenc_context.codedbuf_buf_id);
1656
        CHECK_VASTATUS(va_status,"vaCreateBuffer");
1657
 
1658
        /* Update the RefPicList */
1659
        update_RefPicList();
1660
 
1661
        /* picture parameter set */
1662
        avcenc_update_picture_parameter(slice_type, is_idr);
1663
 
1664
        /* slice parameter */
1665
        avcenc_update_slice_parameter(slice_type);
1666
 
1667
	if (avcenc_context.rate_control_method == VA_RC_CBR)
1668
		avcenc_update_sei_param(is_idr);
1669
 
1670
        avcenc_render_picture();
1671
 
1672
        ret = store_coded_buffer(avc_fp, slice_type);
1673
    } while (ret);
1674
 
1675
    end_picture(slice_type, next_is_bpic);
1676
}
1677
 
1678
static void show_help()
1679
{
1680
    printf("Usage: avnenc     [qp=qpvalue|fb=framebitrate] [mode=0(I frames only)/1(I and P frames)/2(I, P and B frames)\n");
1681
}
1682
 
1683
static void avcenc_context_seq_param_init(VAEncSequenceParameterBufferH264 *seq_param,
1684
                                          int width, int height)
1685
 
1686
{
1687
    int width_in_mbs = (width + 15) / 16;
1688
    int height_in_mbs = (height + 15) / 16;
1689
    int frame_cropping_flag = 0;
1690
    int frame_crop_bottom_offset = 0;
1691
 
1692
    seq_param->seq_parameter_set_id = 0;
1693
    seq_param->level_idc = 41;
1694
    seq_param->intra_period = intra_period;
1695
    seq_param->intra_idr_period = seq_param->intra_period;
1696
    seq_param->ip_period = ip_period;
1697
    seq_param->max_num_ref_frames = 4;
1698
    seq_param->picture_width_in_mbs = width_in_mbs;
1699
    seq_param->picture_height_in_mbs = height_in_mbs;
1700
    seq_param->seq_fields.bits.frame_mbs_only_flag = 1;
1701
    seq_param->seq_fields.bits.chroma_format_idc = 1;
1702
 
1703
 
1704
    if (frame_bit_rate > 0)
1705
        seq_param->bits_per_second = 1000 * frame_bit_rate; /* use kbps as input */
1706
    else
1707
        seq_param->bits_per_second = 0;
1708
 
1709
    seq_param->time_scale = frame_rate * 2;
1710
    seq_param->num_units_in_tick = 1;			/* Tc = num_units_in_tick / time_sacle */
1711
 
1712
    if (height_in_mbs * 16 - height) {
1713
        frame_cropping_flag = 1;
1714
        frame_crop_bottom_offset =
1715
            (height_in_mbs * 16 - height) / (2 * (!seq_param->seq_fields.bits.frame_mbs_only_flag + 1));
1716
    }
1717
 
1718
    seq_param->frame_cropping_flag = frame_cropping_flag;
1719
    seq_param->frame_crop_left_offset = 0;
1720
    seq_param->frame_crop_right_offset = 0;
1721
    seq_param->frame_crop_top_offset = 0;
1722
    seq_param->frame_crop_bottom_offset = frame_crop_bottom_offset;
1723
 
1724
    seq_param->seq_fields.bits.pic_order_cnt_type = 0;
1725
    seq_param->seq_fields.bits.direct_8x8_inference_flag = 0;
1726
 
1727
    seq_param->seq_fields.bits.log2_max_frame_num_minus4 = Log2MaxFrameNum - 4;
1728
    seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = Log2MaxPicOrderCntLsb - 4;
1729
 
1730
    if (frame_bit_rate > 0)
1731
        seq_param->vui_parameters_present_flag = 1;	//HRD info located in vui
1732
    else
1733
        seq_param->vui_parameters_present_flag = 0;
1734
}
1735
 
1736
static void avcenc_context_pic_param_init(VAEncPictureParameterBufferH264 *pic_param)
1737
{
1738
    pic_param->seq_parameter_set_id = 0;
1739
    pic_param->pic_parameter_set_id = 0;
1740
 
1741
    pic_param->last_picture = 0;
1742
    pic_param->frame_num = 0;
1743
 
1744
    pic_param->pic_init_qp = (qp_value >= 0 ?  qp_value : 26);
1745
    pic_param->num_ref_idx_l0_active_minus1 = 0;
1746
    pic_param->num_ref_idx_l1_active_minus1 = 0;
1747
 
1748
    pic_param->pic_fields.bits.idr_pic_flag = 0;
1749
    pic_param->pic_fields.bits.reference_pic_flag = 0;
1750
    pic_param->pic_fields.bits.entropy_coding_mode_flag = ENTROPY_MODE_CABAC;
1751
    pic_param->pic_fields.bits.weighted_pred_flag = 0;
1752
    pic_param->pic_fields.bits.weighted_bipred_idc = 0;
1753
 
1754
    if (avcenc_context.constraint_set_flag & 0x7)
1755
        pic_param->pic_fields.bits.transform_8x8_mode_flag = 0;
1756
    else
1757
        pic_param->pic_fields.bits.transform_8x8_mode_flag = 1;
1758
 
1759
    pic_param->pic_fields.bits.deblocking_filter_control_present_flag = 1;
1760
 
1761
    memset(pic_param->ReferenceFrames, 0xff, 16 * sizeof(VAPictureH264)); /* invalid all */
1762
}
1763
 
1764
static void avcenc_context_sei_init()
1765
{
1766
	int init_cpb_size;
1767
	int target_bit_rate;
1768
 
1769
	/* it comes for the bps defined in SPS */
1770
	target_bit_rate = avcenc_context.seq_param.bits_per_second;
1771
	init_cpb_size = (target_bit_rate * 8) >> 10;
1772
	avcenc_context.i_initial_cpb_removal_delay = 2 * 90000;
1773
	avcenc_context.i_initial_cpb_removal_delay_offset = 2 * 90000;
1774
 
1775
	avcenc_context.i_cpb_removal_delay = 2;
1776
	avcenc_context.i_initial_cpb_removal_delay_length = 24;
1777
	avcenc_context.i_cpb_removal_delay_length = 24;
1778
	avcenc_context.i_dpb_output_delay_length = 24;
1779
	avcenc_context.time_offset_length = 24;
1780
 
1781
        avcenc_context.prev_idr_cpb_removal = avcenc_context.i_initial_cpb_removal_delay / 90000;
1782
        avcenc_context.current_idr_cpb_removal = avcenc_context.prev_idr_cpb_removal;
1783
        avcenc_context.current_cpb_removal = 0;
1784
        avcenc_context.idr_frame_num = 0;
1785
}
1786
 
1787
static void avcenc_context_init(int width, int height)
1788
{
1789
    int i;
1790
    memset(&avcenc_context, 0, sizeof(avcenc_context));
1791
    avcenc_context.profile = VAProfileH264Main;
1792
 
1793
    switch (avcenc_context.profile) {
1794
    case VAProfileH264Baseline:
1795
        avcenc_context.constraint_set_flag |= (1 << 0); /* Annex A.2.1 */
1796
        break;
1797
 
1798
    case VAProfileH264Main:
1799
        avcenc_context.constraint_set_flag |= (1 << 1); /* Annex A.2.2 */
1800
        break;
1801
 
1802
    case VAProfileH264High:
1803
        avcenc_context.constraint_set_flag |= (1 << 3); /* Annex A.2.4 */
1804
        break;
1805
 
1806
    default:
1807
        break;
1808
    }
1809
 
1810
    avcenc_context.seq_param_buf_id = VA_INVALID_ID;
1811
    avcenc_context.pic_param_buf_id = VA_INVALID_ID;
1812
    avcenc_context.packed_seq_header_param_buf_id = VA_INVALID_ID;
1813
    avcenc_context.packed_seq_buf_id = VA_INVALID_ID;
1814
    avcenc_context.packed_pic_header_param_buf_id = VA_INVALID_ID;
1815
    avcenc_context.packed_pic_buf_id = VA_INVALID_ID;
1816
    avcenc_context.codedbuf_buf_id = VA_INVALID_ID;
1817
    avcenc_context.misc_parameter_hrd_buf_id = VA_INVALID_ID;
1818
    avcenc_context.codedbuf_i_size = width * height;
1819
    avcenc_context.codedbuf_pb_size = width * height;
1820
    avcenc_context.current_input_surface = SID_INPUT_PICTURE_0;
1821
    avcenc_context.upload_thread_value = -1;
1822
    avcenc_context.packed_sei_header_param_buf_id = VA_INVALID_ID;
1823
    avcenc_context.packed_sei_buf_id = VA_INVALID_ID;
1824
 
1825
    if (qp_value == -1)
1826
        avcenc_context.rate_control_method = VA_RC_CBR;
1827
    else if (qp_value == -2)
1828
        avcenc_context.rate_control_method = VA_RC_VBR;
1829
    else {
1830
        assert(qp_value >= 0 && qp_value <= 51);
1831
        avcenc_context.rate_control_method = VA_RC_CQP;
1832
    }
1833
 
1834
    for (i = 0; i < MAX_SLICES; i++) {
1835
        avcenc_context.slice_param_buf_id[i] = VA_INVALID_ID;
1836
    }
1837
 
1838
    avcenc_context_seq_param_init(&avcenc_context.seq_param, width, height);
1839
    avcenc_context_pic_param_init(&avcenc_context.pic_param);
1840
    if (avcenc_context.rate_control_method == VA_RC_CBR)
1841
	avcenc_context_sei_init();
1842
}
1843
 
1844
int main(int argc, char *argv[])
1845
{
1846
    int f;
1847
    FILE *yuv_fp;
1848
    FILE *avc_fp;
1849
    off_t file_size;
1850
    int mode_value;
1851
    struct timeval tpstart,tpend;
1852
    float  timeuse;
1853
 
1854
    va_init_display_args(&argc, argv);
1855
 
1856
    //TODO may be we should using option analytics library
1857
    if(argc != 5 && argc != 6 && argc != 7) {
1858
        show_help();
1859
        return -1;
1860
    }
1861
 
1862
    picture_width = atoi(argv[1]);
1863
    picture_height = atoi(argv[2]);
1864
    picture_width_in_mbs = (picture_width + 15) / 16;
1865
    picture_height_in_mbs = (picture_height + 15) / 16;
1866
 
1867
    if (argc == 6 || argc == 7) {
1868
        qp_value = -1;
1869
        sscanf(argv[5], "qp=%d", &qp_value);
1870
        if ( qp_value == -1 ) {
1871
            frame_bit_rate = -1;
1872
            sscanf(argv[5], "fb=%d", &frame_bit_rate);
1873
            if (  frame_bit_rate == -1 ) {
1874
                show_help();
1875
                return -1;
1876
            }
1877
        } else if (qp_value > 51) {
1878
            qp_value = 51;
1879
        } else if (qp_value < 0) {
1880
            qp_value = 0;
1881
        }
1882
    } else
1883
        qp_value = 28;                          //default const QP mode
1884
 
1885
    if (argc == 7) {
1886
        sscanf(argv[6], "mode=%d", &mode_value);
1887
        if ( mode_value == 0 ) {
1888
		ip_period = 0;
1889
        }
1890
        else if ( mode_value == 1) {
1891
		ip_period = 1;
1892
        }
1893
        else if ( mode_value == 2 ) {
1894
		/* Hack mechanism before adding the parameter of B-frame number */
1895
		ip_period = 3;
1896
        }
1897
        else {
1898
                printf("mode_value=%d\n",mode_value);
1899
                show_help();
1900
                return -1;
1901
        }
1902
    }
1903
 
1904
    yuv_fp = fopen(argv[3],"rb");
1905
    if ( yuv_fp == NULL){
1906
        printf("Can't open input YUV file\n");
1907
        return -1;
1908
    }
1909
    fseek(yuv_fp,0l, SEEK_END);
1910
    file_size = ftell(yuv_fp);
1911
    frame_size = picture_width * picture_height +  ((picture_width * picture_height) >> 1) ;
1912
 
1913
    if ( (file_size < frame_size) || (file_size % frame_size) ) {
1914
        fclose(yuv_fp);
1915
        printf("The YUV file's size is not correct\n");
1916
        return -1;
1917
    }
1918
    frame_number = file_size / frame_size;
1919
    fseek(yuv_fp, 0l, SEEK_SET);
1920
 
1921
    avc_fp = fopen(argv[4], "wb");
1922
    if ( avc_fp == NULL) {
1923
        fclose(yuv_fp);
1924
        printf("Can't open output avc file\n");
1925
        return -1;
1926
    }
1927
    gettimeofday(&tpstart,NULL);
1928
    avcenc_context_init(picture_width, picture_height);
1929
    create_encode_pipe();
1930
    alloc_encode_resource(yuv_fp);
1931
 
1932
    enc_frame_number = 0;
1933
    for ( f = 0; f < frame_number; f++) {		//picture level loop
1934
        unsigned long long next_frame_display;
1935
        int next_frame_type;
1936
 
1937
        enc_frame_number = f;
1938
 
1939
        encoding2display_order(enc_frame_number, intra_period, ip_period,
1940
                               ¤t_frame_display, ¤t_frame_type);
1941
 
1942
        encoding2display_order(enc_frame_number + 1, intra_period, ip_period,
1943
                               &next_frame_display, &next_frame_type);
1944
 
1945
        if (current_frame_type == FRAME_IDR) {
1946
            numShortTerm = 0;
1947
            current_frame_num = 0;
1948
            current_IDR_display = current_frame_display;
1949
            if (avcenc_context.rate_control_method == VA_RC_CBR) {
1950
                unsigned long long frame_interval;
1951
 
1952
                frame_interval = enc_frame_number - avcenc_context.idr_frame_num;
1953
 
1954
                /* Based on the H264 spec the removal time of the IDR access
1955
                 * unit is derived as the following:
1956
                 * the removal time of previous IDR unit + Tc * cpb_removal_delay(n)
1957
                 */
1958
                avcenc_context.current_cpb_removal = avcenc_context.prev_idr_cpb_removal +
1959
				frame_interval * 2;
1960
                avcenc_context.idr_frame_num = enc_frame_number;
1961
                avcenc_context.current_idr_cpb_removal = avcenc_context.current_cpb_removal;
1962
                if (ip_period)
1963
                    avcenc_context.current_dpb_removal_delta = (ip_period + 1) * 2;
1964
                else
1965
                    avcenc_context.current_dpb_removal_delta = 2;
1966
            }
1967
        } else {
1968
            if (avcenc_context.rate_control_method == VA_RC_CBR) {
1969
                unsigned long long frame_interval;
1970
 
1971
                frame_interval = enc_frame_number - avcenc_context.idr_frame_num;
1972
 
1973
                /* Based on the H264 spec the removal time of the non-IDR access
1974
                 * unit is derived as the following:
1975
                 * the removal time of current IDR unit + Tc * cpb_removal_delay(n)
1976
                 */
1977
                avcenc_context.current_cpb_removal = avcenc_context.current_idr_cpb_removal +
1978
				frame_interval * 2;
1979
                if (current_frame_type == SLICE_TYPE_I ||
1980
                    current_frame_type == SLICE_TYPE_P) {
1981
                    if (ip_period)
1982
                        avcenc_context.current_dpb_removal_delta = (ip_period + 1) * 2;
1983
                    else
1984
                        avcenc_context.current_dpb_removal_delta = 2;
1985
                } else
1986
                   avcenc_context.current_dpb_removal_delta = 2;
1987
            }
1988
        }
1989
 
1990
        /* use the simple mechanism to calc the POC */
1991
        current_poc = (current_frame_display - current_IDR_display) * 2;
1992
 
1993
        encode_picture(yuv_fp, avc_fp, frame_number, current_frame_display,
1994
                      (current_frame_type == FRAME_IDR) ? 1 : 0,
1995
                      (current_frame_type == FRAME_IDR) ? SLICE_TYPE_I : current_frame_type,
1996
                      (next_frame_type == SLICE_TYPE_B) ? 1 : 0,
1997
                next_frame_display);
1998
        if ((current_frame_type == FRAME_IDR) &&
1999
            (avcenc_context.rate_control_method == VA_RC_CBR)) {
2000
           /* after one IDR frame is written, it needs to update the
2001
            * prev_idr_cpb_removal for next IDR
2002
            */
2003
           avcenc_context.prev_idr_cpb_removal = avcenc_context.current_idr_cpb_removal;
2004
        }
2005
        printf("\r %d/%d ...", f, frame_number);
2006
        fflush(stdout);
2007
    }
2008
 
2009
    gettimeofday(&tpend,NULL);
2010
    timeuse=1000000*(tpend.tv_sec-tpstart.tv_sec)+ tpend.tv_usec-tpstart.tv_usec;
2011
    timeuse/=1000000;
2012
    printf("\ndone!\n");
2013
    printf("encode %d frames in %f secondes, FPS is %.1f\n",frame_number, timeuse, frame_number/timeuse);
2014
    release_encode_resource();
2015
    destory_encode_pipe();
2016
 
2017
    fclose(yuv_fp);
2018
    fclose(avc_fp);
2019
 
2020
    return 0;
2021
}