aboutsummaryrefslogtreecommitdiff
path: root/libvpx/vp8/vp8_cx_iface.c
diff options
context:
space:
mode:
Diffstat (limited to 'libvpx/vp8/vp8_cx_iface.c')
-rw-r--r--libvpx/vp8/vp8_cx_iface.c68
1 files changed, 52 insertions, 16 deletions
diff --git a/libvpx/vp8/vp8_cx_iface.c b/libvpx/vp8/vp8_cx_iface.c
index d01d2095f..1394f2adc 100644
--- a/libvpx/vp8/vp8_cx_iface.c
+++ b/libvpx/vp8/vp8_cx_iface.c
@@ -18,6 +18,7 @@
#include "vpx_mem/vpx_mem.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"
@@ -75,6 +76,9 @@ struct vpx_codec_alg_priv {
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;
@@ -127,6 +131,22 @@ static vpx_codec_err_t update_error_state(
if (!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean"); \
} while (0)
+#if defined(_MSC_VER)
+#define COMPILE_TIME_ASSERT(boolexp) \
+ do { \
+ char compile_time_assert[(boolexp) ? 1 : -1]; \
+ (void)compile_time_assert; \
+ } while (0)
+#else /* !_MSC_VER */
+#define COMPILE_TIME_ASSERT(boolexp) \
+ do { \
+ struct { \
+ unsigned int compile_time_assert : (boolexp) ? 1 : -1; \
+ } compile_time_assert; \
+ (void)compile_time_assert; \
+ } while (0)
+#endif /* _MSC_VER */
+
static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
const vpx_codec_enc_cfg_t *cfg,
const struct vp8_extracfg *vp8_cfg,
@@ -654,6 +674,12 @@ static vpx_codec_err_t vp8e_init(vpx_codec_ctx_t *ctx,
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;
@@ -718,12 +744,14 @@ static void pick_quickcompress_mode(vpx_codec_alg_priv_t *ctx,
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;
+ COMPILE_TIME_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.
@@ -802,6 +830,7 @@ static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx,
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
@@ -822,6 +851,12 @@ static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx,
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);
@@ -871,11 +906,10 @@ static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx,
/* 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);
@@ -914,15 +948,17 @@ static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx,
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;
@@ -941,9 +977,9 @@ static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx,
* 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;
}