diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2020-04-28 20:22:19 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2020-04-28 20:22:19 +0000 |
commit | de4afc881c9dd6daaa0aa11d067f814781459605 (patch) | |
tree | 3ad62ed60696295ea2a29cbf26bf0d3ae25a30d5 | |
parent | 166ed1857b31760b392a80d358407d967c9c0d4a (diff) | |
parent | e49e9629abf962ea496d4761caf49f880a5a8924 (diff) | |
download | libvpx-q_tzdata_aml_297100300.tar.gz |
Snap for 6439596 from e49e9629abf962ea496d4761caf49f880a5a8924 to qt-aml-tzdata-releaseq_tzdata_aml_297100400q_tzdata_aml_297100300q_tzdata_aml_297100000q_tzdata_aml_296200000q_tzdata_aml_295600118q_tzdata_aml_295600110q_tzdata_aml_295500002q_tzdata_aml_295500001q_tzdata_aml_294400310android-mainline-12.0.0_r54android-mainline-12.0.0_r111android-mainline-10.0.0_r13android-mainline-10.0.0_r12android-mainline-10.0.0_r11q_tzdata_aml_297100000android12-mainline-tzdata-releaseandroid10-mainline-tzdata-releaseandroid10-android13-mainline-tzdata-release
Change-Id: I87c4d1d407b9baecefcfc9a4791c6a28f9229bad
-rw-r--r-- | Android.bp | 2 | ||||
-rw-r--r-- | Android.bp.in | 2 | ||||
-rw-r--r-- | README.version | 5 | ||||
-rw-r--r-- | libvpx/examples/vpx_dec_fuzzer.cc | 91 | ||||
-rw-r--r-- | libvpx/vp8/encoder/onyx_int.h | 3 | ||||
-rw-r--r-- | libvpx/vp8/vp8_cx_iface.c | 68 | ||||
-rw-r--r-- | libvpx/vp9/vp9_cx_iface.c | 74 | ||||
-rw-r--r-- | libvpx/vpx_util/vpx_timestamp.h | 45 |
8 files changed, 231 insertions, 59 deletions
diff --git a/Android.bp b/Android.bp index af176c93b..06d6f9c5d 100644 --- a/Android.bp +++ b/Android.bp @@ -1102,7 +1102,7 @@ libvpx_x86_64_asm_srcs = [ "libvpx/vpx_ports/x86_abi_support.asm", ] -cc_library { +cc_library_shared { name: "libvpx", vendor_available: true, version_script: "exports.lds", diff --git a/Android.bp.in b/Android.bp.in index 7cead74e7..97696e56c 100644 --- a/Android.bp.in +++ b/Android.bp.in @@ -1,4 +1,4 @@ -cc_library { +cc_library_shared { name: "libvpx", vendor_available: true, version_script: "exports.lds", diff --git a/README.version b/README.version index 6bc385584..dfc6a897b 100644 --- a/README.version +++ b/README.version @@ -3,3 +3,8 @@ Version: v1.8.0 BugComponent: 42195 Owners: johannkoenig Local Modifications: + - cherry-pick: + * https://chromium-review.googlesource.com/q/Ic6f5eacd9a7c21b95707d31ee2da77dc8ac7dccf + (11de1b838 Fix timestamp overflow issues) + * https://chromium-review.googlesource.com/q/I1d8a6e263fddb9e4cc6265a313011a18d18bbf9e + (04383393e Add missing typecast and re-enable timestamp test) diff --git a/libvpx/examples/vpx_dec_fuzzer.cc b/libvpx/examples/vpx_dec_fuzzer.cc index d55fe1571..b74b47c23 100644 --- a/libvpx/examples/vpx_dec_fuzzer.cc +++ b/libvpx/examples/vpx_dec_fuzzer.cc @@ -32,10 +32,8 @@ * Note --size-limit and VPX_MAX_ALLOCABLE_MEMORY are defined to avoid * Out of memory errors when running generated fuzzer binary $../libvpx/configure --disable-unit-tests --size-limit=12288x12288 \ - --extra-cflags="-fsanitize=fuzzer-no-link \ - -DVPX_MAX_ALLOCABLE_MEMORY=1073741824" \ - --disable-webm-io --enable-debug --disable-vp8-encoder \ - --disable-vp9-encoder --disable-examples + --extra-cflags="-DVPX_MAX_ALLOCABLE_MEMORY=1073741824" \ + --disable-webm-io --enable-debug * Build libvpx $make -j32 @@ -44,7 +42,7 @@ $ $CXX $CXXFLAGS -std=c++11 -DDECODER=vp9 \ -fsanitize=fuzzer -I../libvpx -I. -Wl,--start-group \ ../libvpx/examples/vpx_dec_fuzzer.cc -o ./vpx_dec_fuzzer_vp9 \ - ./libvpx.a -Wl,--end-group + ./libvpx.a ./tools_common.c.o -Wl,--end-group * DECODER should be defined as vp9 or vp8 to enable vp9/vp8 * @@ -66,23 +64,75 @@ #include <stdint.h> #include <stdio.h> #include <stdlib.h> -#include <algorithm> #include <memory> +#include "./tools_common.h" #include "vpx/vp8dx.h" #include "vpx/vpx_decoder.h" #include "vpx_ports/mem_ops.h" -#define IVF_FRAME_HDR_SZ (4 + 8) /* 4 byte size + 8 byte timestamp */ -#define IVF_FILE_HDR_SZ 32 +#define VPX_TOSTRING(str) #str +#define VPX_STRINGIFY(str) VPX_TOSTRING(str) -#define VPXD_INTERFACE(name) VPXD_INTERFACE_(name) -#define VPXD_INTERFACE_(name) vpx_codec_##name##_dx() +static void CloseFile(FILE *file) { fclose(file); } + +/* ReadFrame is derived from ivf_read_frame in ivfdec.c + * This function doesn't call warn(), but instead ignores those errors. + * This is done to minimize the prints on console when running fuzzer + * Also if fread fails to read frame_size number of bytes, instead of + * returning an error, this returns with partial frames. + * This is done to ensure that partial frames are sent to decoder. + */ +static int ReadFrame(FILE *infile, uint8_t **buffer, size_t *bytes_read, + size_t *buffer_size) { + char raw_header[IVF_FRAME_HDR_SZ] = { 0 }; + size_t frame_size = 0; + + if (fread(raw_header, IVF_FRAME_HDR_SZ, 1, infile) == 1) { + frame_size = mem_get_le32(raw_header); + + if (frame_size > 256 * 1024 * 1024) { + frame_size = 0; + } + + if (frame_size > *buffer_size) { + uint8_t *new_buffer = (uint8_t *)realloc(*buffer, 2 * frame_size); + + if (new_buffer) { + *buffer = new_buffer; + *buffer_size = 2 * frame_size; + } else { + frame_size = 0; + } + } + } + + if (!feof(infile)) { + *bytes_read = fread(*buffer, 1, frame_size, infile); + return 0; + } + + return 1; +} extern "C" void usage_exit(void) { exit(EXIT_FAILURE); } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (size <= IVF_FILE_HDR_SZ) { + std::unique_ptr<FILE, decltype(&CloseFile)> file( + fmemopen((void *)data, size, "rb"), &CloseFile); + if (file == nullptr) { + return 0; + } + // Ensure input contains at least one file header and one frame header + if (size < IVF_FILE_HDR_SZ + IVF_FRAME_HDR_SZ) { + return 0; + } + char header[IVF_FILE_HDR_SZ]; + if (fread(header, 1, IVF_FILE_HDR_SZ, file.get()) != IVF_FILE_HDR_SZ) { + return 0; + } + const VpxInterface *decoder = get_vpx_decoder_by_name(VPX_STRINGIFY(DECODER)); + if (decoder == nullptr) { return 0; } @@ -90,29 +140,24 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // Set thread count in the range [1, 64]. const unsigned int threads = (data[IVF_FILE_HDR_SZ] & 0x3f) + 1; vpx_codec_dec_cfg_t cfg = { threads, 0, 0 }; - if (vpx_codec_dec_init(&codec, VPXD_INTERFACE(DECODER), &cfg, 0)) { + if (vpx_codec_dec_init(&codec, decoder->codec_interface(), &cfg, 0)) { return 0; } - data += IVF_FILE_HDR_SZ; - size -= IVF_FILE_HDR_SZ; - - while (size > IVF_FRAME_HDR_SZ) { - size_t frame_size = mem_get_le32(data); - size -= IVF_FRAME_HDR_SZ; - data += IVF_FRAME_HDR_SZ; - frame_size = std::min(size, frame_size); + uint8_t *buffer = nullptr; + size_t buffer_size = 0; + size_t frame_size = 0; + while (!ReadFrame(file.get(), &buffer, &frame_size, &buffer_size)) { const vpx_codec_err_t err = - vpx_codec_decode(&codec, data, frame_size, nullptr, 0); + vpx_codec_decode(&codec, buffer, frame_size, nullptr, 0); static_cast<void>(err); vpx_codec_iter_t iter = nullptr; vpx_image_t *img = nullptr; while ((img = vpx_codec_get_frame(&codec, &iter)) != nullptr) { } - data += frame_size; - size -= frame_size; } vpx_codec_destroy(&codec); + free(buffer); return 0; } diff --git a/libvpx/vp8/encoder/onyx_int.h b/libvpx/vp8/encoder/onyx_int.h index 603de8bcb..7d1c6ab73 100644 --- a/libvpx/vp8/encoder/onyx_int.h +++ b/libvpx/vp8/encoder/onyx_int.h @@ -57,6 +57,9 @@ extern "C" { #define VP8_TEMPORAL_ALT_REF !CONFIG_REALTIME_ONLY +/* vp8 uses 10,000,000 ticks/second as time stamp */ +#define TICKS_PER_SEC 10000000 + typedef struct { int kf_indicated; unsigned int frames_since_key; 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; } diff --git a/libvpx/vp9/vp9_cx_iface.c b/libvpx/vp9/vp9_cx_iface.c index 85f83a662..374f862f9 100644 --- a/libvpx/vp9/vp9_cx_iface.c +++ b/libvpx/vp9/vp9_cx_iface.c @@ -15,6 +15,7 @@ #include "vpx/vpx_encoder.h" #include "vpx_ports/vpx_once.h" #include "vpx_ports/system_state.h" +#include "vpx_util/vpx_timestamp.h" #include "vpx/internal/vpx_codec_internal.h" #include "./vpx_version.h" #include "vp9/encoder/vp9_encoder.h" @@ -94,6 +95,9 @@ struct vpx_codec_alg_priv { vpx_codec_priv_t base; vpx_codec_enc_cfg_t cfg; struct vp9_extracfg extra_cfg; + vpx_rational64_t timestamp_ratio; + vpx_codec_pts_t pts_offset; + unsigned char pts_offset_initialized; VP9EncoderConfig oxcf; VP9_COMP *cpi; unsigned char *cx_data; @@ -151,6 +155,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 vp9_extracfg *extra_cfg) { @@ -915,6 +935,12 @@ static vpx_codec_err_t encoder_init(vpx_codec_ctx_t *ctx, res = validate_config(priv, &priv->cfg, &priv->extra_cfg); if (res == VPX_CODEC_OK) { + 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_encoder_config(&priv->oxcf, &priv->cfg, &priv->extra_cfg); #if CONFIG_VP9_HIGHBITDEPTH priv->oxcf.use_highbitdepth = @@ -951,12 +977,14 @@ static void pick_quickcompress_mode(vpx_codec_alg_priv_t *ctx, switch (ctx->cfg.g_pass) { case VPX_RC_ONE_PASS: if (deadline > 0) { - const vpx_codec_enc_cfg_t *const cfg = &ctx->cfg; - // Convert duration parameter from stream timebase to microseconds. - const uint64_t duration_us = (uint64_t)duration * 1000000 * - (uint64_t)cfg->g_timebase.num / - (uint64_t)cfg->g_timebase.den; + uint64_t duration_us; + + 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. @@ -1040,15 +1068,16 @@ static int write_superframe_index(vpx_codec_alg_priv_t *ctx) { return index_sz; } -static int64_t timebase_units_to_ticks(const vpx_rational_t *timebase, +static int64_t timebase_units_to_ticks(const vpx_rational64_t *timestamp_ratio, int64_t n) { - return n * TICKS_PER_SEC * timebase->num / timebase->den; + return n * timestamp_ratio->num / timestamp_ratio->den; } -static int64_t ticks_to_timebase_units(const vpx_rational_t *timebase, +static int64_t ticks_to_timebase_units(const vpx_rational64_t *timestamp_ratio, int64_t n) { - const int64_t round = (int64_t)TICKS_PER_SEC * timebase->num / 2 - 1; - return (n * timebase->den + round) / timebase->num / TICKS_PER_SEC; + int64_t round = timestamp_ratio->num / 2; + if (round > 0) --round; + return (n * timestamp_ratio->den + round) / timestamp_ratio->num; } static vpx_codec_frame_flags_t get_frame_pkt_flags(const VP9_COMP *cpi, @@ -1078,7 +1107,7 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t *ctx, volatile vpx_codec_err_t res = VPX_CODEC_OK; volatile vpx_enc_frame_flags_t flags = enc_flags; VP9_COMP *const cpi = ctx->cpi; - const vpx_rational_t *const timebase = &ctx->cfg.g_timebase; + const vpx_rational64_t *const timestamp_ratio = &ctx->timestamp_ratio; size_t data_sz; if (cpi == NULL) return VPX_CODEC_INVALID_PARAM; @@ -1112,6 +1141,12 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t *ctx, } } + if (!ctx->pts_offset_initialized) { + ctx->pts_offset = pts; + ctx->pts_offset_initialized = 1; + } + pts -= ctx->pts_offset; + pick_quickcompress_mode(ctx, duration, deadline); vpx_codec_pkt_list_init(&ctx->pkt_list); @@ -1144,13 +1179,13 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t *ctx, if (res == VPX_CODEC_OK) { unsigned int lib_flags = 0; YV12_BUFFER_CONFIG sd; - int64_t dst_time_stamp = timebase_units_to_ticks(timebase, pts); + int64_t dst_time_stamp = timebase_units_to_ticks(timestamp_ratio, pts); int64_t dst_end_time_stamp = - timebase_units_to_ticks(timebase, pts + duration); + timebase_units_to_ticks(timestamp_ratio, pts + duration); size_t size, cx_data_sz; unsigned char *cx_data; - cpi->svc.timebase_fac = timebase_units_to_ticks(timebase, 1); + cpi->svc.timebase_fac = timebase_units_to_ticks(timestamp_ratio, 1); cpi->svc.time_stamp_superframe = dst_time_stamp; // Set up internal flags @@ -1213,9 +1248,10 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t *ctx, if (ctx->output_cx_pkt_cb.output_cx_pkt) { pkt.kind = VPX_CODEC_CX_FRAME_PKT; pkt.data.frame.pts = - ticks_to_timebase_units(timebase, dst_time_stamp); + ticks_to_timebase_units(timestamp_ratio, dst_time_stamp) + + ctx->pts_offset; pkt.data.frame.duration = (unsigned long)ticks_to_timebase_units( - timebase, dst_end_time_stamp - dst_time_stamp); + timestamp_ratio, dst_end_time_stamp - dst_time_stamp); pkt.data.frame.flags = get_frame_pkt_flags(cpi, lib_flags); pkt.data.frame.buf = ctx->pending_cx_data; pkt.data.frame.sz = size; @@ -1231,9 +1267,11 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t *ctx, // Add the frame packet to the list of returned packets. pkt.kind = VPX_CODEC_CX_FRAME_PKT; - pkt.data.frame.pts = ticks_to_timebase_units(timebase, dst_time_stamp); + pkt.data.frame.pts = + ticks_to_timebase_units(timestamp_ratio, dst_time_stamp) + + ctx->pts_offset; pkt.data.frame.duration = (unsigned long)ticks_to_timebase_units( - timebase, dst_end_time_stamp - dst_time_stamp); + timestamp_ratio, dst_end_time_stamp - dst_time_stamp); pkt.data.frame.flags = get_frame_pkt_flags(cpi, lib_flags); pkt.data.frame.width[cpi->svc.spatial_layer_id] = cpi->common.width; pkt.data.frame.height[cpi->svc.spatial_layer_id] = cpi->common.height; diff --git a/libvpx/vpx_util/vpx_timestamp.h b/libvpx/vpx_util/vpx_timestamp.h new file mode 100644 index 000000000..c210de5e5 --- /dev/null +++ b/libvpx/vpx_util/vpx_timestamp.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef VPX_VPX_UTIL_VPX_TIMESTAMP_H_ +#define VPX_VPX_UTIL_VPX_TIMESTAMP_H_ + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// Rational Number with an int64 numerator +typedef struct vpx_rational64 { + int64_t num; // fraction numerator + int den; // fraction denominator +} vpx_rational64_t; // alias for struct vpx_rational64_t + +static INLINE int gcd(int64_t a, int b) { + int r; // remainder + while (b > 0) { + r = (int)(a % b); + a = b; + b = r; + } + + return (int)a; +} + +static INLINE void reduce_ratio(vpx_rational64_t *ratio) { + const int denom = gcd(ratio->num, ratio->den); + ratio->num /= denom; + ratio->den /= denom; +} + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // VPX_VPX_UTIL_VPX_TIMESTAMP_H_ |