* arch/sim/src/sim/sim_x264encoder.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
* Included Files
****************************************************************************/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <linux/videodev2.h>
#include <x264.h>
#include "sim_x264encoder.h"
* Private Types
****************************************************************************/
struct x264_wrapper_s
{
x264_t *enc_ctx;
x264_picture_t pic_in;
x264_picture_t pic_out;
x264_nal_t *nal;
x264_param_t param;
int i_nal;
int remaining_frames;
};
* Public Functions
****************************************************************************/
struct x264_wrapper_s *x264_wrapper_open(void)
{
return calloc(1, sizeof(struct x264_wrapper_s));
}
int x264_wrapper_close(struct x264_wrapper_s *encoder)
{
free(encoder);
return 0;
}
int x264_wrapper_streamon(struct x264_wrapper_s *encoder,
int width, int height, int fps, int bframe)
{
int ret;
memset(&encoder->param, 0, sizeof(x264_param_t));
ret = x264_param_default_preset(&encoder->param,
"fast",
"zerolatency");
if (ret < 0)
{
return ret;
}
encoder->param.i_width = width;
encoder->param.i_height = height;
encoder->param.i_fps_num = fps;
encoder->param.i_fps_den = 1;
encoder->param.b_annexb = 1;
encoder->param.i_csp = X264_CSP_I420;
encoder->param.i_keyint_max = 50;
encoder->param.i_keyint_min = 25;
encoder->param.i_bframe = bframe;
ret = x264_picture_alloc(&encoder->pic_in,
X264_CSP_I420,
width,
height);
if (ret < 0)
{
return ret;
}
encoder->enc_ctx = x264_encoder_open(&encoder->param);
if (!encoder->enc_ctx)
{
x264_picture_clean(&encoder->pic_in);
return -EINVAL;
}
return 0;
}
int x264_wrapper_streamoff(struct x264_wrapper_s *encoder)
{
x264_encoder_close(encoder->enc_ctx);
x264_picture_clean(&encoder->pic_in);
encoder->remaining_frames = 0;
return 0;
}
int x264_wrapper_enqueue(struct x264_wrapper_s *encoder,
uint8_t *data, uint32_t size, int64_t pts)
{
int ret;
if (data != NULL)
{
int width = encoder->param.i_width;
int height = encoder->param.i_height;
encoder->pic_in.i_pts = pts;
memcpy(encoder->pic_in.img.plane[0], data, width * height);
memcpy(encoder->pic_in.img.plane[1], data + width * height,
width * height / 4);
memcpy(encoder->pic_in.img.plane[2], data + width * height * 5 / 4,
width * height / 4);
}
ret = x264_encoder_encode(encoder->enc_ctx,
&encoder->nal,
&encoder->i_nal,
(data != NULL ? &encoder->pic_in : NULL),
&encoder->pic_out);
if (data == NULL)
{
encoder->remaining_frames =
x264_encoder_delayed_frames(encoder->enc_ctx);
}
if (ret >= 0)
{
return 1;
}
return ret;
}
int x264_wrapper_dequeue(struct x264_wrapper_s *encoder,
uint8_t *data, uint32_t *size,
int64_t *pts, uint32_t *flags)
{
int total_size = 0;
int i;
for (i = 0; i < encoder->i_nal; i++)
{
memcpy(data + total_size,
encoder->nal[i].p_payload, encoder->nal[i].i_payload);
total_size += encoder->nal[i].i_payload;
}
*size = total_size;
*pts = encoder->pic_out.i_pts;
switch (encoder->pic_out.i_type)
{
case X264_TYPE_IDR:
case X264_TYPE_I:
*flags = V4L2_BUF_FLAG_KEYFRAME;
break;
case X264_TYPE_P:
*flags = V4L2_BUF_FLAG_PFRAME;
break;
case X264_TYPE_B:
case X264_TYPE_BREF:
*flags = V4L2_BUF_FLAG_BFRAME;
break;
}
return encoder->remaining_frames;
}