#include "vpx/internal/vpx_codec_internal.h"
#include "vpx_version.h"
#include "vpx_mem/vpx_mem.h"
+#include "vpx_ports/static_assert.h"
#include "vpx_ports/system_state.h"
#include "vpx_ports/vpx_once.h"
+#include "vpx_util/vpx_timestamp.h"
#include "vp8/encoder/onyx_int.h"
#include "vpx/vp8cx.h"
#include "vp8/encoder/firstpass.h"
vpx_codec_priv_t base;
vpx_codec_enc_cfg_t cfg;
struct vp8_extracfg vp8_cfg;
+ vpx_rational64_t timestamp_ratio;
+ vpx_codec_pts_t pts_offset;
+ unsigned char pts_offset_initialized;
VP8_CONFIG oxcf;
struct VP8_COMP *cpi;
unsigned char *cx_data;
const vpx_image_t *img) {
switch (img->fmt) {
case VPX_IMG_FMT_YV12:
- case VPX_IMG_FMT_I420: break;
+ case VPX_IMG_FMT_I420:
+ case VPX_IMG_FMT_NV12: break;
default:
- ERROR("Invalid image format. Only YV12 and I420 images are supported");
+ ERROR(
+ "Invalid image format. Only YV12, I420 and NV12 images are "
+ "supported");
}
if ((img->d_w != ctx->cfg.g_w) || (img->d_h != ctx->cfg.g_h))
static vpx_codec_err_t vp8e_mr_alloc_mem(const vpx_codec_enc_cfg_t *cfg,
void **mem_loc) {
- vpx_codec_err_t res = 0;
+ vpx_codec_err_t res = VPX_CODEC_OK;
#if CONFIG_MULTI_RES_ENCODING
LOWER_RES_FRAME_INFO *shared_mem_loc;
shared_mem_loc = calloc(1, sizeof(LOWER_RES_FRAME_INFO));
if (!shared_mem_loc) {
- res = VPX_CODEC_MEM_ERROR;
+ return VPX_CODEC_MEM_ERROR;
}
shared_mem_loc->mb_info =
calloc(mb_rows * mb_cols, sizeof(LOWER_RES_MB_INFO));
if (!(shared_mem_loc->mb_info)) {
+ free(shared_mem_loc);
res = VPX_CODEC_MEM_ERROR;
} else {
*mem_loc = (void *)shared_mem_loc;
res = validate_config(priv, &priv->cfg, &priv->vp8_cfg, 0);
if (!res) {
+ priv->pts_offset_initialized = 0;
+ priv->timestamp_ratio.den = priv->cfg.g_timebase.den;
+ priv->timestamp_ratio.num = (int64_t)priv->cfg.g_timebase.num;
+ priv->timestamp_ratio.num *= TICKS_PER_SEC;
+ reduce_ratio(&priv->timestamp_ratio);
+
set_vp8e_config(&priv->oxcf, priv->cfg, priv->vp8_cfg, mr_cfg);
priv->cpi = vp8_create_compressor(&priv->oxcf);
if (!priv->cpi) res = VPX_CODEC_MEM_ERROR;
new_qc = MODE_BESTQUALITY;
if (deadline) {
+ /* Convert duration parameter from stream timebase to microseconds */
uint64_t duration_us;
- /* Convert duration parameter from stream timebase to microseconds */
- duration_us = (uint64_t)duration * 1000000 *
- (uint64_t)ctx->cfg.g_timebase.num /
- (uint64_t)ctx->cfg.g_timebase.den;
+ VPX_STATIC_ASSERT(TICKS_PER_SEC > 1000000 &&
+ (TICKS_PER_SEC % 1000000) == 0);
+
+ duration_us = duration * (uint64_t)ctx->timestamp_ratio.num /
+ (ctx->timestamp_ratio.den * (TICKS_PER_SEC / 1000000));
/* If the deadline is more that the duration this frame is to be shown,
* use good quality mode. Otherwise use realtime mode.
volatile vpx_codec_err_t res = VPX_CODEC_OK;
// Make a copy as volatile to avoid -Wclobbered with longjmp.
volatile vpx_enc_frame_flags_t flags = enc_flags;
+ volatile vpx_codec_pts_t pts_val = pts;
if (!ctx->cfg.rc_target_bitrate) {
#if CONFIG_MULTI_RES_ENCODING
if (!res) res = validate_config(ctx, &ctx->cfg, &ctx->vp8_cfg, 1);
+ if (!ctx->pts_offset_initialized) {
+ ctx->pts_offset = pts_val;
+ ctx->pts_offset_initialized = 1;
+ }
+ pts_val -= ctx->pts_offset;
+
pick_quickcompress_mode(ctx, duration, deadline);
vpx_codec_pkt_list_init(&ctx->pkt_list);
/* Convert API flags to internal codec lib flags */
lib_flags = (flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0;
- /* vp8 use 10,000,000 ticks/second as time stamp */
dst_time_stamp =
- pts * 10000000 * ctx->cfg.g_timebase.num / ctx->cfg.g_timebase.den;
- dst_end_time_stamp = (pts + duration) * 10000000 * ctx->cfg.g_timebase.num /
- ctx->cfg.g_timebase.den;
+ pts_val * ctx->timestamp_ratio.num / ctx->timestamp_ratio.den;
+ dst_end_time_stamp = (pts_val + (int64_t)duration) *
+ ctx->timestamp_ratio.num / ctx->timestamp_ratio.den;
if (img != NULL) {
res = image2yuvconfig(img, &sd);
VP8_COMP *cpi = (VP8_COMP *)ctx->cpi;
/* Add the frame packet to the list of returned packets. */
- round = (vpx_codec_pts_t)10000000 * ctx->cfg.g_timebase.num / 2 - 1;
+ round = (vpx_codec_pts_t)ctx->timestamp_ratio.num / 2;
+ if (round > 0) --round;
delta = (dst_end_time_stamp - dst_time_stamp);
pkt.kind = VPX_CODEC_CX_FRAME_PKT;
pkt.data.frame.pts =
- (dst_time_stamp * ctx->cfg.g_timebase.den + round) /
- ctx->cfg.g_timebase.num / 10000000;
+ (dst_time_stamp * ctx->timestamp_ratio.den + round) /
+ ctx->timestamp_ratio.num +
+ ctx->pts_offset;
pkt.data.frame.duration =
- (unsigned long)((delta * ctx->cfg.g_timebase.den + round) /
- ctx->cfg.g_timebase.num / 10000000);
+ (unsigned long)((delta * ctx->timestamp_ratio.den + round) /
+ ctx->timestamp_ratio.num);
pkt.data.frame.flags = lib_flags << 16;
pkt.data.frame.width[0] = cpi->common.Width;
pkt.data.frame.height[0] = cpi->common.Height;
* Invisible frames have no duration.
*/
pkt.data.frame.pts =
- ((cpi->last_time_stamp_seen * ctx->cfg.g_timebase.den + round) /
- ctx->cfg.g_timebase.num / 10000000) +
- 1;
+ ((cpi->last_time_stamp_seen * ctx->timestamp_ratio.den + round) /
+ ctx->timestamp_ratio.num) +
+ ctx->pts_offset + 1;
pkt.data.frame.duration = 0;
}