From b0f1d9c501cdc2daca72b6f4f2b82566e001c473 Mon Sep 17 00:00:00 2001 From: Boris Grozev <boris@jitsi.org> Date: Fri, 25 Jan 2013 17:05:32 +0000 Subject: [PATCH] Adds a JNI interface to libvpx via the org.jitsi.impl.neomedia.codec.video.VPX class. Adds a VP8 encoder and decoder based on that interface. --- .../org_jitsi_impl_neomedia_codec_video_VPX.c | 726 +++++++++++++ .../org_jitsi_impl_neomedia_codec_video_VPX.h | 623 +++++++++++ ...impl_neomedia_codec_video_VPX_StreamInfo.h | 13 + .../jitsi/impl/neomedia/codec/video/VPX.java | 993 ++++++++++++++++++ .../neomedia/codec/video/vp8/VPXDecoder.java | 355 +++++++ .../neomedia/codec/video/vp8/VPXEncoder.java | 459 ++++++++ 6 files changed, 3169 insertions(+) create mode 100644 src/native/vpx/org_jitsi_impl_neomedia_codec_video_VPX.c create mode 100644 src/native/vpx/org_jitsi_impl_neomedia_codec_video_VPX.h create mode 100644 src/native/vpx/org_jitsi_impl_neomedia_codec_video_VPX_StreamInfo.h create mode 100644 src/org/jitsi/impl/neomedia/codec/video/VPX.java create mode 100644 src/org/jitsi/impl/neomedia/codec/video/vp8/VPXDecoder.java create mode 100644 src/org/jitsi/impl/neomedia/codec/video/vp8/VPXEncoder.java diff --git a/src/native/vpx/org_jitsi_impl_neomedia_codec_video_VPX.c b/src/native/vpx/org_jitsi_impl_neomedia_codec_video_VPX.c new file mode 100644 index 00000000..d8e7a8cf --- /dev/null +++ b/src/native/vpx/org_jitsi_impl_neomedia_codec_video_VPX.c @@ -0,0 +1,726 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +#include <stdlib.h> +#include <string.h> +#include "org_jitsi_impl_neomedia_codec_video_VPX.h" + +#include "vpx/vpx_decoder.h" +#include "vpx/vpx_encoder.h" +#include "vpx/vp8dx.h" +#include "vpx/vp8cx.h" +#define VPX_CODEC_DISABLE_COMPAT 1 + +/* Convert the INTERFACE_* constants defined in java to + the (vpx_codec_iface_t *)'s used in libvpx */ +#define GET_INTERFACE(x) \ + (((x) == org_jitsi_impl_neomedia_codec_video_VPX_INTEFACE_VP8_DEC) \ + ? vpx_codec_vp8_dx() \ + : (((x) == org_jitsi_impl_neomedia_codec_video_VPX_INTERFACE_VP8_ENC)) \ + ? vpx_codec_vp8_cx() \ + : NULL) + +#define DEFINE_ENC_CFG_INT_PROPERTY_SETTER(name, property) \ + JNIEXPORT void JNICALL \ + Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1cfg_1set_1##name \ + (JNIEnv *env, jclass clazz, jlong cfg, jint value) \ + { \ + ((vpx_codec_enc_cfg_t *) (intptr_t) cfg)->property = (int) value; \ + } + +#define DEFINE_IMG_INT_PROPERTY_SETTER(name, property) \ + JNIEXPORT void JNICALL \ + Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1set_1##name \ + (JNIEnv *env, jclass clazz, jlong img, jint value) \ + { \ + ((vpx_image_t *) (intptr_t) img)->property = (int) value; \ + } + + +/* + * Method: codec_ctx_malloc + */ +JNIEXPORT jlong JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1ctx_1malloc + (JNIEnv *env, + jclass clazz) +{ + return (jlong) (intptr_t) malloc(sizeof(vpx_codec_ctx_t)); +} + +/* + * Method: codec_dec_init + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1dec_1init + (JNIEnv *env, + jclass clazz, + jlong context, + jint iface, + jlong cfg, + jlong flags) +{ + return (jint) vpx_codec_dec_init( + (vpx_codec_ctx_t *) (intptr_t) context, + GET_INTERFACE(iface), + (vpx_codec_dec_cfg_t *) (intptr_t) cfg, + (vpx_codec_flags_t) flags); +} + +/* + * Method: codec_decode + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1decode + (JNIEnv *env, + jclass clazz, + jlong context, + jbyteArray buf, + jint buf_offset, + jint buf_size, + jlong user_priv, + jlong deadline) +{ + jbyte *buf_ptr = (*env)->GetByteArrayElements(env, buf, NULL); + + vpx_codec_err_t ret; + ret = vpx_codec_decode((vpx_codec_ctx_t *) (intptr_t) context, + (uint8_t *) (buf_ptr + buf_offset), + (unsigned int) buf_size, + (void *) (intptr_t) user_priv, + (long) deadline); + (*env)->ReleaseByteArrayElements(env, buf, buf_ptr, JNI_ABORT); + return (jint) ret; +} + +/* + * Method: codec_get_frame + */ +JNIEXPORT jlong JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1get_1frame + (JNIEnv *env, + jclass clazz, + jlong context, + jlongArray iterArray) +{ + jlong *iter_ptr = (*env)->GetLongArrayElements(env, iterArray, NULL); + + vpx_image_t *ret; + ret = vpx_codec_get_frame((vpx_codec_ctx_t *) (intptr_t) context, + (vpx_codec_iter_t *) iter_ptr); + + (*env)->ReleaseLongArrayElements(env, iterArray, iter_ptr, 0); + return (jlong) (intptr_t) ret; +} + +/* + * Method: codec_destroy + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1destroy + (JNIEnv *env, + jclass clazz, + jlong context) +{ + return (jint) vpx_codec_destroy((vpx_codec_ctx_t *) (intptr_t) context); +} + +/* + * Method: codec_get_mem_map + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1get_1mem_1map + (JNIEnv *env, + jclass clazz, + jlong context, + jlongArray mmapArray, + jlongArray iterArray) +{ + jlong *iter_ptr = (*env)->GetLongArrayElements(env, iterArray, NULL); + jlong *mmap_ptr = (*env)->GetLongArrayElements(env, mmapArray, NULL); + + vpx_codec_err_t ret; + ret = vpx_codec_get_mem_map((vpx_codec_ctx_t *) (intptr_t) context, + (vpx_codec_mmap_t *) mmap_ptr, + (vpx_codec_iter_t *) iter_ptr); + + (*env)->ReleaseLongArrayElements(env, iterArray, iter_ptr, 0); + (*env)->ReleaseLongArrayElements(env, mmapArray, mmap_ptr, 0); + + return (jint) ret; +} + +/* + * Method: codec_set_mem_map + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1set_1mem_1map + (JNIEnv *env, + jclass clazz, + jlong context, + jlong mmap, + jint count) +{ + vpx_codec_err_t ret; + ret = vpx_codec_set_mem_map((vpx_codec_ctx_t *) (intptr_t) context, + (vpx_codec_mmap_t *) (intptr_t) mmap, + (unsigned int) count); + return (jint) ret; +} + +/* + * Method: codec_enc_init + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1init + (JNIEnv *env, + jclass clazz, + jlong context, + jint iface, + jlong cfg, + jlong flags) +{ + return (jint) vpx_codec_enc_init( + (vpx_codec_ctx_t *) (intptr_t) context, + GET_INTERFACE(iface), + (vpx_codec_enc_cfg_t *) (intptr_t) cfg, + (vpx_codec_flags_t) flags); +} + +/* + * Method: codec_enc_config_set + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1config_1set + (JNIEnv *env, + jclass clazz, + jlong context, + jlong cfg) +{ + return (jint) vpx_codec_enc_config_set( + (vpx_codec_ctx_t *) (intptr_t) context, + (vpx_codec_enc_cfg_t *) (intptr_t) context); +} + +/* + * Method: codec_encode + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1encode + (JNIEnv *env, + jclass clazz, + jlong context, + jlong jimg, + jbyteArray bufArray, + jint offset0, + jint offset1, + jint offset2, + jlong pts, + jlong duration, + jlong flags, + jlong deadline) +{ + unsigned char *buf + = (unsigned char *) (*env)->GetByteArrayElements(env, bufArray, NULL); + vpx_image_t *img = (vpx_image_t *) (intptr_t) jimg; + img->planes[0] = (buf + offset0); + img->planes[1] = (buf + offset1); + img->planes[2] = (buf + offset2); + img->planes[3] = 0; + + jint ret = (jint) vpx_codec_encode( + (vpx_codec_ctx_t *) (intptr_t) context, + img, + (vpx_codec_pts_t) pts, + (unsigned long) duration, + (vpx_enc_frame_flags_t) flags, + (unsigned long) deadline); + + (*env)->ReleaseByteArrayElements(env, bufArray, (jbyte *)buf, JNI_ABORT); + return ret; +} + +/* + * Method: codec_get_cx_data + */ +JNIEXPORT jlong JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1get_1cx_1data + (JNIEnv *env, + jclass clazz, + jlong context, + jlongArray iterArray) +{ + jlong *iter_ptr = (*env)->GetLongArrayElements(env, iterArray, NULL); + + const vpx_codec_cx_pkt_t *ret; + ret = vpx_codec_get_cx_data((vpx_codec_ctx_t *) (intptr_t) context, + (vpx_codec_iter_t *) iter_ptr); + + (*env)->ReleaseLongArrayElements(env, iterArray, iter_ptr, 0); + return (jlong) (intptr_t) ret; + +} + +/* + * Method: codec_cx_pkt_get_kind + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1cx_1pkt_1get_1kind + (JNIEnv *env, + jclass clazz, + jlong pkt) +{ + jint ret = (jint) ((vpx_codec_cx_pkt_t *) (intptr_t) pkt)->kind; + return ret; +} + +/* + * Method: codec_cx_pkt_get_size + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1cx_1pkt_1get_1size + (JNIEnv *env, + jclass clazz, + jlong pkt) +{ + return (jint) ((vpx_codec_cx_pkt_t *) (intptr_t) pkt)->data.frame.sz; +} + +/* + * Method: codec_cx_pkt_get_data + */ +JNIEXPORT jlong JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1cx_1pkt_1get_1data + (JNIEnv *env, + jclass clazz, + jlong pkt) +{ + return (jlong) (intptr_t) + ((vpx_codec_cx_pkt_t *) (intptr_t) pkt)->data.frame.buf; +} + +/* + * Method: img_malloc + */ +JNIEXPORT jlong JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1malloc + (JNIEnv *env, + jclass clazz) +{ + return (jlong) (intptr_t) malloc(sizeof(vpx_image_t)); +} + +/* + * Method: img_get_w + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1get_1w + (JNIEnv *env, + jclass clazz, + jlong img) +{ + return (jint) ((vpx_image_t *) (intptr_t) img)->w; +} + +/* + * Method: img_get_h + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1get_1h + (JNIEnv *env, + jclass clazz, + jlong img) +{ + return (jint) ((vpx_image_t *) (intptr_t) img)->h; +} + +/* + * Method: img_get_d_w + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1get_1d_1w + (JNIEnv *env, + jclass clazz, + jlong img) +{ + return (jint) ((vpx_image_t *) (intptr_t) img)->d_w; +} + +/* + * Method: img_get_d_h + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1get_1d_1h + (JNIEnv *env, + jclass clazz, + jlong img) +{ + return (jint) ((vpx_image_t *) (intptr_t) img)->d_h; +} + +/* + * Method: img_get_plane0 + */ +JNIEXPORT jlong JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1get_1plane0 + (JNIEnv *env, + jclass clazz, + jlong img) +{ + return (jlong) (intptr_t) ((vpx_image_t *) (intptr_t) img)->planes[0]; +} + +/* + * Method: img_get_plane1 + */ +JNIEXPORT jlong JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1get_1plane1 + (JNIEnv *env, + jclass clazz, + jlong img) +{ + return (jlong) (intptr_t) ((vpx_image_t *) (intptr_t) img)->planes[1]; +} + +/* + * Method: img_get_plane2 + */ +JNIEXPORT jlong JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1get_1plane2 + (JNIEnv *env, + jclass clazz, + jlong img) +{ + return (jlong) (intptr_t) ((vpx_image_t *) (intptr_t) img)->planes[2]; +} + +/* + * Method: img_get_stride0 + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1get_1stride0 + (JNIEnv *env, + jclass clazz, + jlong img) +{ + return (jint) ((vpx_image_t *) (intptr_t) img)->stride[0]; +} + +/* + * Method: img_get_stride1 + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1get_1stride1 + (JNIEnv *env, + jclass clazz, + jlong img) +{ + return (jint) ((vpx_image_t *) (intptr_t) img)->stride[1]; +} + +/* + * Method: img_get_stride2 + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1get_1stride2 + (JNIEnv *env, + jclass clazz, + jlong img) +{ + return (jint) ((vpx_image_t *) (intptr_t) img)->stride[2]; +} + +/* + * Method: img_get_fmt + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1get_1fmt + (JNIEnv *env, + jclass clazz, + jlong img) +{ + return (jint) ((vpx_image_t *) (intptr_t) img)->fmt; +} + +DEFINE_IMG_INT_PROPERTY_SETTER(w, w) +DEFINE_IMG_INT_PROPERTY_SETTER(h, h) +DEFINE_IMG_INT_PROPERTY_SETTER(d_1w, d_w) +DEFINE_IMG_INT_PROPERTY_SETTER(d_1h, d_h) +DEFINE_IMG_INT_PROPERTY_SETTER(stride0, stride[0]) +DEFINE_IMG_INT_PROPERTY_SETTER(stride1, stride[1]) +DEFINE_IMG_INT_PROPERTY_SETTER(stride2, stride[2]) +DEFINE_IMG_INT_PROPERTY_SETTER(stride3, stride[3]) +DEFINE_IMG_INT_PROPERTY_SETTER(fmt, fmt) +DEFINE_IMG_INT_PROPERTY_SETTER(bps, bps) + +/* + * Method: img_wrap + */ +JNIEXPORT void JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1wrap + (JNIEnv *env, + jclass clazz, + jlong img, + jint fmt, + jint d_w, + jint d_h, + jint align, + jlong data) +{ + vpx_img_wrap((vpx_image_t *) (intptr_t) img, + (vpx_img_fmt_t) fmt, + (unsigned int) d_w, + (unsigned int) d_h, + (unsigned int) align, + (unsigned char *) (intptr_t) data); +} + +/* + * Method: codec_dec_cfg_malloc + */ +JNIEXPORT jlong JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1dec_1cfg_1malloc + (JNIEnv *env, + jclass clazz) +{ + return (jlong) (intptr_t) malloc(sizeof(vpx_codec_dec_cfg_t)); +} + +/* + * Method: codec_dec_cfg_set_w + */ +JNIEXPORT void JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1dec_1cfg_1set_1w + (JNIEnv *env, + jclass clazz, + jlong cfg, + jint width) +{ + ((vpx_codec_dec_cfg_t *) (intptr_t) cfg)->w = width; +} + +/* + * Method: codec_dec_cfg_set_w + */ +JNIEXPORT void JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1dec_1cfg_1set_1h + (JNIEnv *env, + jclass clazz, + jlong cfg, + jint height) +{ + ((vpx_codec_dec_cfg_t *) (intptr_t) cfg)->h = height; +} + +/* + * Method: codec_enc_cfg_malloc + */ +JNIEXPORT jlong JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1cfg_1malloc + (JNIEnv *env, jclass clazz) +{ + return (jlong) (intptr_t) malloc(sizeof(vpx_codec_enc_cfg_t)); +} + + +/* + * Method: codec_enc_config_default + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1config_1default + (JNIEnv *env, + jclass clazz, + jint iface, + jlong cfg, + jint usage) +{ + return vpx_codec_enc_config_default( + GET_INTERFACE(iface), + (vpx_codec_enc_cfg_t *) (intptr_t) cfg, + (int) usage); +} + +DEFINE_ENC_CFG_INT_PROPERTY_SETTER(profile, g_profile) +DEFINE_ENC_CFG_INT_PROPERTY_SETTER(threads, g_threads) +DEFINE_ENC_CFG_INT_PROPERTY_SETTER(w, g_w) +DEFINE_ENC_CFG_INT_PROPERTY_SETTER(h, g_h) +DEFINE_ENC_CFG_INT_PROPERTY_SETTER(rc_1target_1bitrate, rc_target_bitrate) +DEFINE_ENC_CFG_INT_PROPERTY_SETTER(rc_1dropframe_1thresh, rc_dropframe_thresh) +DEFINE_ENC_CFG_INT_PROPERTY_SETTER(rc_1resize_1allowed, rc_resize_allowed) +DEFINE_ENC_CFG_INT_PROPERTY_SETTER(rc_1resize_1up_1thresh, rc_resize_up_thresh) +DEFINE_ENC_CFG_INT_PROPERTY_SETTER(rc_1resize_1down_1thresh, rc_resize_down_thresh) +DEFINE_ENC_CFG_INT_PROPERTY_SETTER(rc_1end_1usage, rc_end_usage) +DEFINE_ENC_CFG_INT_PROPERTY_SETTER(rc_1min_1quantizer, rc_min_quantizer) +DEFINE_ENC_CFG_INT_PROPERTY_SETTER(rc_1max_1quantizer, rc_max_quantizer) +DEFINE_ENC_CFG_INT_PROPERTY_SETTER(rc_1undershoot_1pct, rc_undershoot_pct) +DEFINE_ENC_CFG_INT_PROPERTY_SETTER(rc_1overshoot_1pct, rc_overshoot_pct) +DEFINE_ENC_CFG_INT_PROPERTY_SETTER(rc_1buf_1sz, rc_buf_sz) +DEFINE_ENC_CFG_INT_PROPERTY_SETTER(rc_1buf_1initial_1sz, rc_buf_initial_sz) +DEFINE_ENC_CFG_INT_PROPERTY_SETTER(rc_1buf_1optimal_1sz, rc_buf_optimal_sz) +DEFINE_ENC_CFG_INT_PROPERTY_SETTER(kf_1mode, kf_mode) +DEFINE_ENC_CFG_INT_PROPERTY_SETTER(kf_1min_1dist, kf_min_dist) +DEFINE_ENC_CFG_INT_PROPERTY_SETTER(kf_1max_1dist, kf_max_dist) + +/* + * Method: stream_info_malloc + */ +JNIEXPORT jlong JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_stream_1info_1malloc + (JNIEnv *env, + jclass clazz) +{ + return (jlong) (intptr_t) malloc(sizeof(vpx_codec_stream_info_t)); +} + +/* + * Method: stream_info_get_w + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_stream_1info_1get_1w + (JNIEnv *env, + jclass clazz, + jlong si) +{ + return (jint) ((vpx_codec_stream_info_t *) (intptr_t) si)->w; +} + +/* + * Method: stream_info_get_h + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_stream_1info_1get_1h + (JNIEnv *env, + jclass clazz, + jlong si) +{ + return (jint) ((vpx_codec_stream_info_t *) (intptr_t) si)->h; +} + +/* + * Method: stream_info_get_is_kf + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_stream_1info_1get_1is_1kf + (JNIEnv *env, + jclass clazz, + jlong si) +{ + return (jint) ((vpx_codec_stream_info_t *) (intptr_t) si)->h; +} + +/* + * Method: codec_peek_stream_info + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1peek_1stream_1info + (JNIEnv *env, + jclass clazz, + jint iface, + jbyteArray buf, + jint buf_offset, + jint buf_size, + jlong si) +{ + vpx_codec_err_t ret; + jbyte *buf_ptr = (*env)->GetByteArrayElements(env, buf, NULL); + + ret = vpx_codec_peek_stream_info(GET_INTERFACE(iface), + (uint8_t *) (buf_ptr + buf_offset), + buf_size, + (vpx_codec_stream_info_t *) (intptr_t)si); + (*env)->ReleaseByteArrayElements(env, buf, buf_ptr, JNI_ABORT); + return ret; +} + +/* + * Method: codec_mmap_get_sz + */ +JNIEXPORT jlong JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1mmap_1get_1sz + (JNIEnv *env, + jclass clazz, + jlong map) +{ + return (jlong) ((vpx_codec_mmap_t *) (intptr_t) map)->sz; +} + +/* + * Method: codec_mmap_set_base + */ +JNIEXPORT void JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1mmap_1set_1base + (JNIEnv *env, + jclass clazz, + jlong map, + jlong base) +{ + ((vpx_codec_mmap_t *) (intptr_t) map)->base = (void *) (intptr_t) base; +} + +/* + * Method: malloc + */ +JNIEXPORT jlong JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_malloc + (JNIEnv *env, + jclass clazz, + jlong size) +{ + return (jlong) (intptr_t) malloc((size_t) size); +} + +/* + * Method: free + */ +JNIEXPORT void JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_free + (JNIEnv *env, + jclass clazz, + jlong ptr) +{ + free((void *) (intptr_t) ptr); +} + +/* + * Method: memcpy + */ +JNIEXPORT void JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_memcpy + (JNIEnv *env, + jclass clazz, + jbyteArray dstArray, + jlong src, + jint n) +{ + jbyte *dst = (*env)->GetByteArrayElements(env, dstArray, NULL); + memcpy(dst, (char *) (intptr_t) src, n); + (*env)->ReleaseByteArrayElements(env, dstArray, dst, 0); +} + +/* + * Method: codec_err_to_string + */ +JNIEXPORT jint JNICALL +Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1err_1to_1string + (JNIEnv *env, + jclass clazz, + jint err, + jbyteArray buf, + jint buf_size) +{ + const char *err_str = vpx_codec_err_to_string((vpx_codec_err_t) err); + jbyte *buf_ptr = (*env)->GetByteArrayElements(env, buf, NULL); + + int i; + for(i = 0; i < buf_size-1 && err_str[i] != '\0'; i++) + buf_ptr[i] = (jbyte) err_str[i]; + buf_ptr[i] = (jbyte) '\0'; + + (*env)->ReleaseByteArrayElements(env, buf, buf_ptr, 0); + + return i; +} + diff --git a/src/native/vpx/org_jitsi_impl_neomedia_codec_video_VPX.h b/src/native/vpx/org_jitsi_impl_neomedia_codec_video_VPX.h new file mode 100644 index 00000000..16c62bbe --- /dev/null +++ b/src/native/vpx/org_jitsi_impl_neomedia_codec_video_VPX.h @@ -0,0 +1,623 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include <jni.h> +/* Header for class org_jitsi_impl_neomedia_codec_video_VPX */ + +#ifndef _Included_org_jitsi_impl_neomedia_codec_video_VPX +#define _Included_org_jitsi_impl_neomedia_codec_video_VPX +#ifdef __cplusplus +extern "C" { +#endif +#undef org_jitsi_impl_neomedia_codec_video_VPX_CODEC_OK +#define org_jitsi_impl_neomedia_codec_video_VPX_CODEC_OK 0L +#undef org_jitsi_impl_neomedia_codec_video_VPX_CODEC_LIST_END +#define org_jitsi_impl_neomedia_codec_video_VPX_CODEC_LIST_END 9L +#undef org_jitsi_impl_neomedia_codec_video_VPX_CODEC_USE_XMA +#define org_jitsi_impl_neomedia_codec_video_VPX_CODEC_USE_XMA 1L +#undef org_jitsi_impl_neomedia_codec_video_VPX_IMG_FMT_I420 +#define org_jitsi_impl_neomedia_codec_video_VPX_IMG_FMT_I420 258L +#undef org_jitsi_impl_neomedia_codec_video_VPX_RC_MODE_VBR +#define org_jitsi_impl_neomedia_codec_video_VPX_RC_MODE_VBR 0L +#undef org_jitsi_impl_neomedia_codec_video_VPX_RC_MODE_CBR +#define org_jitsi_impl_neomedia_codec_video_VPX_RC_MODE_CBR 1L +#undef org_jitsi_impl_neomedia_codec_video_VPX_RC_MODE_CQ +#define org_jitsi_impl_neomedia_codec_video_VPX_RC_MODE_CQ 2L +#undef org_jitsi_impl_neomedia_codec_video_VPX_KF_MODE_AUTO +#define org_jitsi_impl_neomedia_codec_video_VPX_KF_MODE_AUTO 1L +#undef org_jitsi_impl_neomedia_codec_video_VPX_KF_MODE_DISABLED +#define org_jitsi_impl_neomedia_codec_video_VPX_KF_MODE_DISABLED 1L +#undef org_jitsi_impl_neomedia_codec_video_VPX_DL_REALTIME +#define org_jitsi_impl_neomedia_codec_video_VPX_DL_REALTIME 1L +#undef org_jitsi_impl_neomedia_codec_video_VPX_CODEC_CX_FRAME_PKT +#define org_jitsi_impl_neomedia_codec_video_VPX_CODEC_CX_FRAME_PKT 0L +#undef org_jitsi_impl_neomedia_codec_video_VPX_INTEFACE_VP8_DEC +#define org_jitsi_impl_neomedia_codec_video_VPX_INTEFACE_VP8_DEC 0L +#undef org_jitsi_impl_neomedia_codec_video_VPX_INTERFACE_VP8_ENC +#define org_jitsi_impl_neomedia_codec_video_VPX_INTERFACE_VP8_ENC 1L +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_ctx_malloc + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1ctx_1malloc + (JNIEnv *, jclass); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_dec_init + * Signature: (JIJJ)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1dec_1init + (JNIEnv *, jclass, jlong, jint, jlong, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_decode + * Signature: (J[BIIJJ)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1decode + (JNIEnv *, jclass, jlong, jbyteArray, jint, jint, jlong, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_get_frame + * Signature: (J[J)J + */ +JNIEXPORT jlong JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1get_1frame + (JNIEnv *, jclass, jlong, jlongArray); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_destroy + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1destroy + (JNIEnv *, jclass, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_get_mem_map + * Signature: (J[J[J)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1get_1mem_1map + (JNIEnv *, jclass, jlong, jlongArray, jlongArray); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_set_mem_map + * Signature: (JJI)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1set_1mem_1map + (JNIEnv *, jclass, jlong, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_init + * Signature: (JIJJ)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1init + (JNIEnv *, jclass, jlong, jint, jlong, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_config_set + * Signature: (JJ)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1config_1set + (JNIEnv *, jclass, jlong, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_encode + * Signature: (JJ[BIIIJJJJ)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1encode + (JNIEnv *, jclass, jlong, jlong, jbyteArray, jint, jint, jint, jlong, jlong, jlong, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_get_cx_data + * Signature: (J[J)J + */ +JNIEXPORT jlong JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1get_1cx_1data + (JNIEnv *, jclass, jlong, jlongArray); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_cx_pkt_get_kind + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1cx_1pkt_1get_1kind + (JNIEnv *, jclass, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_cx_pkt_get_size + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1cx_1pkt_1get_1size + (JNIEnv *, jclass, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_cx_pkt_get_data + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1cx_1pkt_1get_1data + (JNIEnv *, jclass, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: img_malloc + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1malloc + (JNIEnv *, jclass); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: img_get_w + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1get_1w + (JNIEnv *, jclass, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: img_get_h + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1get_1h + (JNIEnv *, jclass, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: img_get_d_w + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1get_1d_1w + (JNIEnv *, jclass, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: img_get_d_h + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1get_1d_1h + (JNIEnv *, jclass, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: img_get_plane0 + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1get_1plane0 + (JNIEnv *, jclass, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: img_get_plane1 + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1get_1plane1 + (JNIEnv *, jclass, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: img_get_plane2 + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1get_1plane2 + (JNIEnv *, jclass, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: img_get_stride0 + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1get_1stride0 + (JNIEnv *, jclass, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: img_get_stride1 + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1get_1stride1 + (JNIEnv *, jclass, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: img_get_stride2 + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1get_1stride2 + (JNIEnv *, jclass, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: img_get_fmt + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1get_1fmt + (JNIEnv *, jclass, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: img_set_w + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1set_1w + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: img_set_h + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1set_1h + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: img_set_d_w + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1set_1d_1w + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: img_set_d_h + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1set_1d_1h + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: img_set_stride0 + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1set_1stride0 + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: img_set_stride1 + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1set_1stride1 + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: img_set_stride2 + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1set_1stride2 + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: img_set_stride3 + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1set_1stride3 + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: img_set_fmt + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1set_1fmt + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: img_set_bps + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1set_1bps + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: img_wrap + * Signature: (JIIIIJ)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_img_1wrap + (JNIEnv *, jclass, jlong, jint, jint, jint, jint, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_dec_cfg_malloc + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1dec_1cfg_1malloc + (JNIEnv *, jclass); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_dec_cfg_set_w + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1dec_1cfg_1set_1w + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_dec_cfg_set_h + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1dec_1cfg_1set_1h + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_cfg_malloc + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1cfg_1malloc + (JNIEnv *, jclass); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_config_default + * Signature: (IJI)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1config_1default + (JNIEnv *, jclass, jint, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_cfg_set_profile + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1cfg_1set_1profile + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_cfg_set_threads + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1cfg_1set_1threads + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_cfg_set_w + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1cfg_1set_1w + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_cfg_set_h + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1cfg_1set_1h + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_cfg_set_rc_target_bitrate + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1cfg_1set_1rc_1target_1bitrate + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_cfg_set_rc_dropframe_thresh + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1cfg_1set_1rc_1dropframe_1thresh + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_cfg_set_rc_resize_allowed + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1cfg_1set_1rc_1resize_1allowed + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_cfg_set_rc_resize_up_thresh + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1cfg_1set_1rc_1resize_1up_1thresh + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_cfg_set_rc_resize_down_thresh + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1cfg_1set_1rc_1resize_1down_1thresh + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_cfg_set_rc_end_usage + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1cfg_1set_1rc_1end_1usage + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_cfg_set_rc_min_quantizer + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1cfg_1set_1rc_1min_1quantizer + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_cfg_set_rc_max_quantizer + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1cfg_1set_1rc_1max_1quantizer + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_cfg_set_rc_undershoot_pct + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1cfg_1set_1rc_1undershoot_1pct + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_cfg_set_rc_overshoot_pct + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1cfg_1set_1rc_1overshoot_1pct + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_cfg_set_rc_buf_sz + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1cfg_1set_1rc_1buf_1sz + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_cfg_set_rc_buf_initial_sz + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1cfg_1set_1rc_1buf_1initial_1sz + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_cfg_set_rc_buf_optimal_sz + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1cfg_1set_1rc_1buf_1optimal_1sz + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_cfg_set_kf_mode + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1cfg_1set_1kf_1mode + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_cfg_set_kf_min_dist + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1cfg_1set_1kf_1min_1dist + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_enc_cfg_set_kf_max_dist + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1enc_1cfg_1set_1kf_1max_1dist + (JNIEnv *, jclass, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: stream_info_malloc + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_stream_1info_1malloc + (JNIEnv *, jclass); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: stream_info_get_w + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_stream_1info_1get_1w + (JNIEnv *, jclass, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: stream_info_get_h + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_stream_1info_1get_1h + (JNIEnv *, jclass, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: stream_info_get_is_kf + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_stream_1info_1get_1is_1kf + (JNIEnv *, jclass, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_peek_stream_info + * Signature: (I[BIIJ)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1peek_1stream_1info + (JNIEnv *, jclass, jint, jbyteArray, jint, jint, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_mmap_get_sz + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1mmap_1get_1sz + (JNIEnv *, jclass, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_mmap_set_base + * Signature: (JJ)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1mmap_1set_1base + (JNIEnv *, jclass, jlong, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: malloc + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_malloc + (JNIEnv *, jclass, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: free + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_free + (JNIEnv *, jclass, jlong); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: memcpy + * Signature: ([BJI)V + */ +JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_memcpy + (JNIEnv *, jclass, jbyteArray, jlong, jint); + +/* + * Class: org_jitsi_impl_neomedia_codec_video_VPX + * Method: codec_err_to_string + * Signature: (I[BI)I + */ +JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_video_VPX_codec_1err_1to_1string + (JNIEnv *, jclass, jint, jbyteArray, jint); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/native/vpx/org_jitsi_impl_neomedia_codec_video_VPX_StreamInfo.h b/src/native/vpx/org_jitsi_impl_neomedia_codec_video_VPX_StreamInfo.h new file mode 100644 index 00000000..7cb5fd1e --- /dev/null +++ b/src/native/vpx/org_jitsi_impl_neomedia_codec_video_VPX_StreamInfo.h @@ -0,0 +1,13 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include <jni.h> +/* Header for class org_jitsi_impl_neomedia_codec_video_VPX_StreamInfo */ + +#ifndef _Included_org_jitsi_impl_neomedia_codec_video_VPX_StreamInfo +#define _Included_org_jitsi_impl_neomedia_codec_video_VPX_StreamInfo +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/org/jitsi/impl/neomedia/codec/video/VPX.java b/src/org/jitsi/impl/neomedia/codec/video/VPX.java new file mode 100644 index 00000000..d44b7928 --- /dev/null +++ b/src/org/jitsi/impl/neomedia/codec/video/VPX.java @@ -0,0 +1,993 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package org.jitsi.impl.neomedia.codec.video; + +/** + * A wrapper for the libvpx native library. + * See {@link "http://www.webmproject.org/docs/"} + * + * @author Boris Grozev + */ +public class VPX { + /** + * Operation completed without error. + * Corresponds to <tt>VPX_CODEC_OK</tt> from <tt>vpx/vpx_codec.h</tt> + */ + public static final int CODEC_OK = 0; + + /** + * An iterator reached the end of list. + * Corresponds to <tt>VPX_CODEC_LIST_END</tt> from <tt>vpx/vpx_codec.h</tt> + */ + public static final int CODEC_LIST_END = 9; + + /** + * Use eXternal Memory Allocation mode flag + * Corresponds to <tt>VPX_CODEC_USE_XMA</tt> from <tt>vpx/vpx_codec.h</tt> + */ + public static final int CODEC_USE_XMA = 0x00000001; + + /** + * I420 format constant + * Corresponds to <tt>VPX_IMG_FMT_I420</tt> from <tt>vpx/vpx_image.h</tt> + + */ + public static final int IMG_FMT_I420 = 258; + + /** + * Variable Bitrate mode. + * Corresponds to <tt>VPX_VBR</tt> from <tt>vpx/vpx_encoder.h</tt> + */ + public static final int RC_MODE_VBR = 0; + + /** + * Constant Bitrate mode. + * Corresponds to <tt>VPX_CBR</tt> from <tt>vpx/vpx_encoder.h</tt> + */ + public static final int RC_MODE_CBR = 1; + + /** + * Constant Quality mode. + * Corresponds to <tt>VPX_CQ</tt> from <tt>vpx/vpx_encoder.h</tt> + */ + public static final int RC_MODE_CQ = 2; + + /** + * Encoder determines optimal placement automatically. + * Corresponds to <tt>VPX_KF_AUTO</tt> from in <tt>vpx/vpx_encoder.h</tt> + */ + public static final int KF_MODE_AUTO = 1; + + /** + * Encoder does not place keyframes. + * Corresponds to <tt>VPX_KF_DISABLED</tt> from <tt>vpx/vpx_encoder.h</tt> + */ + public static final int KF_MODE_DISABLED = 1; + + /** + * Process and return as soon as possible ('realtime' deadline) + * Corresponds to <tt>VPX_DL_REALTIME</tt> from <tt>vpx/vpx_encoder.h</tt> + */ + public static final int DL_REALTIME = 1; + + /** + * Compressed video frame packet type. + * Corresponds to <tt>VPX_CODEC_CX_FRAME_PKT</tt> from + * <tt>vpx/vpx_encoder.h</tt> + */ + public static final int CODEC_CX_FRAME_PKT = 0; + + + /** + * Constant for VP8 decoder interface + */ + public static final int INTEFACE_VP8_DEC = 0; + + /** + * Constant for VP8 encoder interface + */ + public static final int INTERFACE_VP8_ENC = 1; + + /** + * Allocates memory for a <tt>vpx_codec_ctx_t</tt> on the heap. + * + * @return A pointer to the allocated memory. + */ + public static native long codec_ctx_malloc(); + + /** + * Initializes a vpx decoder context. + * @param context Pointer to a pre-allocated <tt>vpx_codec_ctx_t</tt>. + * @param iface Interface to be used. Has to be one of the + * <tt>VPX.INTERFACE_*</tt> constants. + * @param cfg Pointer to a pre-allocated <tt>vpx_codec_dec_cfg_t</tt>, may + * be 0. + * @param flags Flags. + * + * @return <tt>CODEC_OK</tt> on success, or an error code otherwise. The + * error code can be converted to a <tt>String</tt> with + * {@link VPX#codec_err_to_string(int)} + */ + public static native int codec_dec_init(long context, + int iface, + long cfg, + long flags); + + /** + * Decodes the frame in <tt>buf</tt>, at offset <tt>buf_offset</tt>. + * + * @param context The context to use. + * @param buf Encoded frame buffer. + * @param buf_offset Offset into <tt>buf</tt> where the encoded frame begins. + * @param buf_size Size of the encoded frame. + * @param user_priv Application specific data to associate with this frame. + * @param deadline Soft deadline the decoder should attempt to meet, + * in microseconds. Set to zero for unlimited. + * + * @return <tt>CODEC_OK</tt> on success, or an error code otherwise. The + * error code can be converted to a <tt>String</tt> with + * {@link VPX#codec_err_to_string(int)} + */ + public static native int codec_decode(long context, + byte[] buf, + int buf_offset, + int buf_size, + long user_priv, + long deadline); + + /** + * Gets the next frame available to display from the decoder context + * <tt>context</tt>. + * The list of available frames becomes valid upon completion of the + * <tt>codec_decode</tt> call, and remains valid until the next call to + * <tt>codec_decode</tt>. + * + * @param context The decoder context to use. + * @param iter Iterator storage, initialized by setting it's first element + * to 0. + * + * @return Pointer to a <tt>vpx_image_t</tt> describing the decoded frame, + * or 0 if no more frames are available + */ + public static native long codec_get_frame(long context, + long[] iter); + + /** + * Destroys a codec context, freeing any associated memory buffers. + * + * @param context Pointer to the <tt>vpx_codec_ctx_t</tt> context to destroy. + * + * @return <tt>CODEC_OK</tt> on success, or an error code otherwise. The + * error code can be converted to a <tt>String</tt> with + * {@link VPX#codec_err_to_string(int)} + */ + public static native int codec_destroy(long context); + + /** + * Iterate over the list of segments to allocate. + * + * This function can only be used on codec implementations which have the + * XMA (eXternam Memory Allocation) capability. + * + * Iterates over a list of the segments to allocate. The iterator storage + * should be initialized to NULL to start the iteration. Iteration is + * complete when this function returns VPX_CODEC_LIST_END. The amount of + * memory needed to allocate is dependent upon the size of the encoded + * stream. In cases where the stream is not available at allocation time, + * a fixed size must be requested. The codec will not be able to operate on + * streams larger than the size used at allocation time. + * + * @param context The codec context to use. + * @param mmap Pointer to a <tt>vpx_codec_mmap_t</tt> to populate + * @param iter Iterator storage, initialized by setting it's first element + * to 0. + * + * @return <tt>CODEC_OK</tt> on success, or an error code otherwise. The + * error code can be converted to a <tt>String</tt> with + * {@link VPX#codec_err_to_string(int)} + */ + public static native int codec_get_mem_map(long context, + long mmap[], + long[] iter); + + /** + * Identify allocated segments to codec instance. + * + * This function can only be used on codec implementations which have the + * XMA (eXternam Memory Allocation) capability. + * + * @param context The codec context to use. + * @param mmap Pointer to the first memory map entry in the list. + * @param count Number of entries being set at this time. + * + * @return <tt>CODEC_OK</tt> on success, or an error code otherwise. The + * error code can be converted to a <tt>String</tt> with + * {@link VPX#codec_err_to_string(int)} + */ + public static native int codec_set_mem_map(long context, + long mmap, + int count); + + /** + * Initializes a vpx encoder context. + * + * @param context Pointer to a pre-allocated <tt>vpx_codec_ctx_t</tt>. + * @param iface Interface to be used. Has to be one of the + * <tt>VPX.INTERFACE_*</tt> constants. + * @param cfg Pointer to a pre-allocated <tt>vpx_codec_enc_cfg_t</tt>, + * may be 0. + * @param flags Flags. + * + * @return <tt>CODEC_OK</tt> on success, or an error code otherwise. The + * error code can be converted to a <tt>String</tt> with + * {@link VPX#codec_err_to_string(int)} + */ + public static native int codec_enc_init(long context, + int iface, + long cfg, + long flags); + + /** + * + * @param context Pointer to the codec context on which to set the + * confirutation + * @param cfg Pointer to a <tt>vpx_codec_enc_cfg_t</tt> to set. + * + * @return <tt>CODEC_OK</tt> on success, or an error code otherwise. The + * error code can be converted to a <tt>String</tt> with + * {@link VPX#codec_err_to_string(int)} + */ + public static native int codec_enc_config_set(long context, + long cfg); + + /** + * Encodes the frame described by <tt>img</tt>, <tt>buf</tt>, + * <tt>offset0</tt>, <tt>offset1</tt> and <tt>offset2</tt>. + * + * Note that <tt>buf</tt> and the offsets describe where the frames is + * stored, but <tt>img</tt> has to have all of it's other parameters (format, + * dimensions, strides) already set. + * + * The reason <tt>buf</tt> and the offsets are treated differently is to + * allow for the encoder to operate on java memory and avoid copying the raw + * frame to native memory. + * + * @param context Pointer to the codec context to use. + * @param img Pointer to a <tt>vpx_image_t</tt> describing the raw frame + * @param buf Contains the raw frame + * @param offset0 Offset of the first plane + * @param offset1 Offset of the second plane + * @param offset2 Offset of the third plane + * @param pts Presentation time stamp, in timebase units. + * @param duration Duration to show frame, in timebase units. + * @param flags Flags to use for encoding this frame. + * @param deadline Time to spend encoding, in microseconds. (0=infinite) + * + * @return <tt>CODEC_OK</tt> on success, or an error code otherwise. The + * error code can be converted to a <tt>String</tt> with + * {@link VPX#codec_err_to_string(int)} + */ + public static native int codec_encode(long context, + long img, + byte[] buf, + int offset0, + int offset1, + int offset2, + long pts, + long duration, + long flags, + long deadline); + + /** + * Encoded data iterator. + * Iterates over a list of data packets to be passed from the encoder to + * the application. The kind of a packet can be determined using + * {@link VPX#codec_cx_pkt_get_kind} + * Packets of kind <tt>CODEC_CX_FRAME_PKT</tt> should be passed to the + * application's muxer. + * + * @param context The codec context to use. + * @param iter Iterator storage, initialized by setting it's first element + * to 0. + * + * @return Pointer to a vpx_codec_cx_pkt_t containing the output data + * packet, or 0 to indicate the end of available packets + */ + public static native long codec_get_cx_data(long context, + long[] iter); + + /** + * Returns the <tt>kind</tt> of the <tt>vpx_codec_cx_pkt_t</tt> pointed to + * by <tt>pkt</tt>. + * + * @param pkt Pointer to the <tt>vpx_codec_cx_pkt_t</tt> to return the + * <tt>kind</tt> of. + * @return The kind of <tt>pkt</tt>. + */ + public static native int codec_cx_pkt_get_kind(long pkt); + + /** + * Returns the size of the data in the <tt>vpx_codec_cx_pkt_t</tt> pointed + * to by <tt>pkt</tt>. Can only be used for packets of <tt>kind</tt> + * <tt>CODEC_CX_FRAME_PKT</tt>. + * + * @param pkt Pointer to a <tt>vpx_codec_cx_pkt_t</tt>. + * + * @return The size of the data of <tt>pkt</tt>. + */ + public static native int codec_cx_pkt_get_size(long pkt); + + /** + * Returns a pointer to the data in the <tt>vpx_codec_cx_pkt_t</tt> pointed + * to by<tt>pkt</tt>. Can only be used for packets of <tt>kind</tt> + * <tt>CODEC_CX_FRAME_PKT</tt>. + * + * @param pkt Pointer to the <tt>vpx_codec_cx_pkt_t</tt>. + * @return Pointer to the data of <tt>pkt</tt>. + */ + public static native long codec_cx_pkt_get_data(long pkt); + + //img + /** + * Allocates memory for a <tt>vpx_image_t</tt> on the heap. + * + * @return A pointer to the allocated memory. + */ + public static native long img_malloc(); + + /** + * Returns the value of the <tt>w</tt> (width) field of a + * <tt>vpx_image_t</tt>. + * + * @param img Pointer to a <tt>vpx_image_t</tt>. + * + * @return The <tt>w</tt> (width) field of <tt>img</tt>. + */ + public static native int img_get_w(long img); + + /** + * Returns the value of the <tt>h</tt> (height) field of a + * <tt>vpx_image_t</tt>. + * + * @param img Pointer to a <tt>vpx_image_t</tt>. + * + * @return The <tt>h</tt> (height) field of <tt>img</tt>. + */ + public static native int img_get_h(long img); + + /** + * Returns the value of the <tt>d_w</tt> (displayed width) field of a + * <tt>vpx_image_t</tt>. + * + * @param img Pointer to a <tt>vpx_image_t</tt>. + * + * @return The <tt>d_w</tt> (displayed width) field of <tt>img</tt>. + */ + public static native int img_get_d_w(long img); + + /** + * Returns the value of the <tt>d_h</tt> (displayed height) field of a + * <tt>vpx_image_t</tt>. + * + * @param img Pointer to a <tt>vpx_image_t</tt>. + * + * @return The <tt>d_h</tt> (displayed height) field of <tt>img</tt>. + */ + public static native int img_get_d_h(long img); + + /** + * Returns the value of the <tt>planes[0]</tt> field of a + * <tt>vpx_image_t</tt>. + * + * @param img Pointer to a <tt>vpx_image_t</tt>. + * + * @return The <tt>planes[0]</tt> field of <tt>img</tt>. + */ + public static native long img_get_plane0(long img); + + /** + * Returns the value of the <tt>planes[1]</tt> field of a + * <tt>vpx_image_t</tt>. + * + * @param img Pointer to a <tt>vpx_image_t</tt>. + * + * @return The <tt>planes[1]</tt> field of <tt>img</tt>. + */ + public static native long img_get_plane1(long img); + + /** + * Returns the value of the <tt>planes[2]</tt> field of a + * <tt>vpx_image_t</tt>. + * + * @param img Pointer to a <tt>vpx_image_t</tt>. + * + * @return The <tt>planes[2]</tt> field of <tt>img</tt>. + */ + public static native long img_get_plane2(long img); + + /** + * Returns the value of the <tt>stride[0]</tt> field of a + * <tt>vpx_image_t</tt>. + * + * @param img Pointer to a <tt>vpx_image_t</tt>. + * + * @return The <tt>stride[0]</tt> field of <tt>img</tt>. + */ + public static native int img_get_stride0(long img); + + /** + * Returns the value of the <tt>stride[1]</tt> field of a + * <tt>vpx_image_t</tt>. + * + * @param img Pointer to a <tt>vpx_image_t</tt>. + * + * @return The <tt>stride[1]</tt> field of <tt>img</tt>. + */ + public static native int img_get_stride1(long img); + + /** + * Returns the value of the <tt>stride[2]</tt> field of a + * <tt>vpx_image_t</tt>. + * + * @param img Pointer to a <tt>vpx_image_t</tt>. + * + * @return The <tt>stride[2]</tt> field of <tt>img</tt>. + */ + public static native int img_get_stride2(long img); + + /** + * Returns the value of the <tt>fmt</tt> field of a + * <tt>vpx_image_t</tt>. + * + * @param img Pointer to a <tt>vpx_image_t</tt>. + * + * @return The <tt>fmt</tt> field of <tt>img</tt>. + */ + public static native int img_get_fmt(long img); + + /** + * Sets the <tt>w</tt> (width) field of a <tt>vpx_image_t</tt>. + * @param img Pointer to a <tt>vpx_image_t</tt>. + * @param value The value to set. + */ + public static native void img_set_w(long img, int value); + + /** + * Sets the <tt>h</tt> (height) field of a <tt>vpx_image_t</tt>. + * @param img Pointer to a <tt>vpx_image_t</tt>. + * @param value The value to set. + */ + public static native void img_set_h(long img, int value); + + /** + * Sets the <tt>d_w</tt> (displayed width) field of a <tt>vpx_image_t</tt>. + * @param img Pointer to a <tt>vpx_image_t</tt>. + * @param value The value to set. + */ + public static native void img_set_d_w(long img, int value); + + /** + * Sets the <tt>d_h</tt> (displayed height) field of a <tt>vpx_image_t</tt>. + * @param img Pointer to a <tt>vpx_image_t</tt>. + * @param value The value to set. + */ + public static native void img_set_d_h(long img, int value); + + /** + * Sets the <tt>stride[0]</tt> field of a <tt>vpx_image_t</tt>. + * @param img Pointer to a <tt>vpx_image_t</tt>. + * @param value The value to set. + */ + public static native void img_set_stride0(long img, int value); + + /** + * Sets the <tt>stride[1]</tt> field of a <tt>vpx_image_t</tt>. + * @param img Pointer to a <tt>vpx_image_t</tt>. + * @param value The value to set. + */ + public static native void img_set_stride1(long img, int value); + + /** + * Sets the <tt>stride[2]</tt> field of a <tt>vpx_image_t</tt>. + * @param img Pointer to a <tt>vpx_image_t</tt>. + * @param value The value to set. + */ + public static native void img_set_stride2(long img, int value); + + /** + * Sets the <tt>stride[3]</tt> field of a <tt>vpx_image_t</tt>. + * @param img Pointer to a <tt>vpx_image_t</tt>. + * @param value The value to set. + */ + public static native void img_set_stride3(long img, int value); + + /** + * Sets the <tt>fmt</tt> (format) field of a <tt>vpx_image_t</tt>. + * @param img Pointer to a <tt>vpx_image_t</tt>. + * @param value The value to set. + */ + public static native void img_set_fmt(long img, int value); + + /** + * Sets the <tt>bps</tt> (bits per sample) field of a <tt>vpx_image_t</tt>. + * @param img Pointer to a <tt>vpx_image_t</tt>. + * @param value The value to set. + */ + public static native void img_set_bps(long img, int value); + + /** + * Open a descriptor, using existing storage for the underlying image. + * + * Returns a descriptor for storing an image of the given format. The + * storage for descriptor has been allocated elsewhere, and a descriptor is + * desired to "wrap" that storage. + * + * @param img Pointer to a <tt>vpx_image_t</tt>. + * @param fmt Format of the image. + * @param d_w Width of the image. + * @param d_h Height of the image. + * @param align Alignment, in bytes, of each row in the image. + * @param data Storage to use for the image + */ + public static native void img_wrap(long img, + int fmt, + int d_w, + int d_h, + int align, + long data); + + /** + * Allocates memory for a <tt>vpx_codec_dec_cfg_t</tt> on the heap. + * + * @return A pointer to the allocated memory. + */ + public static native long codec_dec_cfg_malloc(); + + /** + * Sets the <tt>w</tt> field of a <tt>vpx_codec_dec_cfg_t</tt>. + * + * @param cfg Pointer to a <tt>vpx_codec_dec_cfg_t</tt>. + * @param value The value to set. + */ + public static native void codec_dec_cfg_set_w(long cfg, int value); + + /** + * Sets the <tt>h</tt> field of a <tt>vpx_codec_dec_cfg_t</tt>. + * + * @param cfg Pointer to a <tt>vpx_codec_dec_cfg_t</tt>. + * @param value The value to set. + */ + public static native void codec_dec_cfg_set_h(long cfg, int value); + + /** + * Allocates memory for a <tt>vpx_codec_enc_cfg_t</tt> on the heap. + * + * @return A pointer to the allocated memory. + */ + public static native long codec_enc_cfg_malloc(); + + /** + * Initializes a encoder configuration structure with default values. + * + * @param iface Interface. Should be one of the <tt>INTERFACE_*</tt> + * constants + * @param cfg Pointer to the vpx_codec_enc_cfg_t to initialize + * @param usage End usage. Set to 0 or use codec specific values. + * + * @return <tt>CODEC_OK</tt> on success, or an error code otherwise. The + * error code can be converted to a <tt>String</tt> with + * {@link VPX#codec_err_to_string(int)} + */ + public static native int codec_enc_config_default(int iface, + long cfg, + int usage); + + /** + * Sets the <tt>g_profile</tt> field of a <tt>vpx_codec_enc_cfg_t</tt>. + * + * @param cfg Pointer to a <tt>vpx_codec_enc_cfg_t</tt> + * @param value The value to set. + */ + public static native void codec_enc_cfg_set_profile(long cfg, + int value); + + /** + * Sets the <tt>g_threads</tt> field of a <tt>vpx_codec_enc_cfg_t</tt>. + * + * @param cfg Pointer to a <tt>vpx_codec_enc_cfg_t</tt>. + * @param value The value to set. + */ + public static native void codec_enc_cfg_set_threads(long cfg, + int value); + + /** + * Sets the <tt>g_w</tt> field of a <tt>vpx_codec_enc_cfg_t</tt>. + * + * @param cfg Pointer to a <tt>vpx_codec_enc_cfg_t</tt>. + * @param value The value to set. + */ + public static native void codec_enc_cfg_set_w(long cfg, + int value); + + /** + * Sets the <tt>g_h</tt> field of a <tt>vpx_codec_enc_cfg_t</tt>. + * + * @param cfg Pointer to a <tt>vpx_codec_enc_cfg_t</tt>. + * @param value The value to set. + */ + public static native void codec_enc_cfg_set_h(long cfg, + int value); + + /** + * Sets the <tt>rc_target_bitrate</tt> field of a + * <tt>vpx_codec_enc_cfg_t</tt>. + * + * @param cfg Pointer to a <tt>vpx_codec_enc_cfg_t</tt>. + * @param value The value to set. + */ + public static native void codec_enc_cfg_set_rc_target_bitrate(long cfg, + int value); + + /** + * Sets the <tt>rc_dropframe_thresh</tt> field of a + * <tt>vpx_codec_enc_cfg_t</tt>. + * + * @param cfg Pointer to a <tt>vpx_codec_enc_cfg_t</tt>. + * @param value The value to set. + */ + public static native void codec_enc_cfg_set_rc_dropframe_thresh(long cfg, + int value); + + /** + * Sets the <tt>rc_resize_allowed</tt> field of a + * <tt>vpx_codec_enc_cfg_t</tt>. + * + * @param cfg Pointer to a <tt>vpx_codec_enc_cfg_t</tt>. + * @param value The value to set. + */ + public static native void codec_enc_cfg_set_rc_resize_allowed(long cfg, + int value); + + /** + * Sets the <tt>rc_resize_up_thresh</tt> field of a + * <tt>vpx_codec_enc_cfg_t</tt>. + * + * @param cfg Pointer to a <tt>vpx_codec_enc_cfg_t</tt>. + * @param value The value to set. + */ + public static native void codec_enc_cfg_set_rc_resize_up_thresh(long cfg, + int value); + + /** + * Sets the <tt>rc_resize_down_thresh</tt> field of a + * <tt>vpx_codec_enc_cfg_t</tt>. + * + * @param cfg Pointer to a <tt>vpx_codec_enc_cfg_t</tt>. + * @param value The value to set. + */ + public static native void codec_enc_cfg_set_rc_resize_down_thresh(long cfg, + int value); + + /** + * Sets the <tt>rc_end_usage</tt> field of a <tt>vpx_codec_enc_cfg_t</tt>. + * + * @param cfg Pointer to a <tt>vpx_codec_enc_cfg_t</tt>. + * @param value The value to set. + */ + public static native void codec_enc_cfg_set_rc_end_usage(long cfg, + int value); + + /** + * Sets the <tt>rc_min_quantizer</tt> field of a <tt>vpx_codec_enc_cfg_t</tt>. + * + * @param cfg Pointer to a <tt>vpx_codec_enc_cfg_t</tt>. + * @param value The value to set. + */ + public static native void codec_enc_cfg_set_rc_min_quantizer(long cfg, + int value); + + /** + * Sets the <tt>rc_max_quantizer</tt> field of a <tt>vpx_codec_enc_cfg_t</tt>. + * + * @param cfg Pointer to a <tt>vpx_codec_enc_cfg_t</tt>. + * @param value The value to set. + */ + public static native void codec_enc_cfg_set_rc_max_quantizer(long cfg, + int value); + + /** + * Sets the <tt>rc_undershoot_pct</tt> field of a <tt>vpx_codec_enc_cfg_t</tt>. + * + * @param cfg Pointer to a <tt>vpx_codec_enc_cfg_t</tt>. + * @param value The value to set. + */ + public static native void codec_enc_cfg_set_rc_undershoot_pct(long cfg, + int value); + + /** + * Sets the <tt>rc_overshoot_pct</tt> field of a + * <tt>vpx_codec_enc_cfg_t</tt>. + * + * @param cfg Pointer to a <tt>vpx_codec_enc_cfg_t</tt>. + * @param value The value to set. + */ + public static native void codec_enc_cfg_set_rc_overshoot_pct(long cfg, + int value); + + /** + * Sets the <tt>rc_buf_sz</tt> field of a <tt>vpx_codec_enc_cfg_t</tt>. + * + * @param cfg Pointer to a <tt>vpx_codec_enc_cfg_t</tt>. + * @param value The value to set. + */ + public static native void codec_enc_cfg_set_rc_buf_sz(long cfg, + int value); + + /** + * Sets the <tt>rc_buf_initial_sz</tt> field of a + * <tt>vpx_codec_enc_cfg_t</tt>. + * + * @param cfg Pointer to a <tt>vpx_codec_enc_cfg_t</tt>. + * @param value The value to set. + */ + public static native void codec_enc_cfg_set_rc_buf_initial_sz(long cfg, + int value); + + /** + * Sets the <tt>rc_buf_optimal_sz</tt> field of a + * <tt>vpx_codec_enc_cfg_t</tt>. + * + * @param cfg Pointer to a <tt>vpx_codec_enc_cfg_t</tt>. + * @param value The value to set. + */ + public static native void codec_enc_cfg_set_rc_buf_optimal_sz(long cfg, + int value); + + /** + * Sets the <tt>kf_mode</tt> field of a <tt>vpx_codec_enc_cfg_t</tt>. + * + * @param cfg Pointer to a <tt>vpx_codec_enc_cfg_t</tt>. + * @param value The value to set. + */ + public static native void codec_enc_cfg_set_kf_mode(long cfg, + int value); + + /** + * Sets the <tt>kf_min_dist</tt> field of a <tt>vpx_codec_enc_cfg_t</tt>. + * + * @param cfg Pointer to a <tt>vpx_codec_enc_cfg_t</tt>. + * @param value The value to set. + */ + public static native void codec_enc_cfg_set_kf_min_dist(long cfg, + int value); + + /** + * Sets the <tt>kf_max_dist</tt> field of a <tt>vpx_codec_enc_cfg_t</tt>. + * + * @param cfg Pointer to a <tt>vpx_codec_enc_cfg_t</tt>. + * @param value The value to set. + */ + public static native void codec_enc_cfg_set_kf_max_dist(long cfg, + int value); + + /** + * Allocates memory for a <tt>vpx_codec_stream_info_t</tt> on the heap. + * + * @return A pointer to the allocated memory. + */ + public static native long stream_info_malloc(); + + + /** + * Returns the <tt>w</tt> field of a <tt>vpx_codec_stream_info_t</tt>. + * + * @param stream_info Pointer to a <tt>vpx_codec_stream_info_t</tt>. + * + * @return The <tt>w</tt> field of a <tt>stream_info</tt>. + */ + public static native int stream_info_get_w(long stream_info); + + /** + * Returns the <tt>h</tt> field of a <tt>vpx_codec_stream_info_t</tt>. + * + * @param stream_info Pointer to a <tt>vpx_codec_stream_info_t</tt>. + * + * @return The <tt>h</tt> field of a <tt>stream_info</tt>. + */ + public static native int stream_info_get_h(long stream_info); + + + /** + * Returns the <tt>is_kf</tt> field of a <tt>vpx_codec_stream_info_t</tt>. + * + * @param stream_info Pointer to a <tt>vpx_codec_stream_info_t</tt>. + * + * @return The <tt>w</tt> field of a <tt>stream_info</tt>. + */ + public static native int stream_info_get_is_kf(long stream_info); + + + /** + * Performs high level parsing of the bitstream. Construction of a decoder + * context is not necessary. Can be used to determine if the bitstream is + * of the proper format, and to extract information from the stream. + * + * @param iface Interface, should be one of the <tt>INTERFACE_*</tt> + * constants. + * @param buf Buffer containing a compressed frame. + * @param buf_offset Offset into <tt>buf</tt> where the compressed frame + * begins. + * @param buf_size Size of the compressed frame. + * @param si_ptr Pointer to a <tt>vpx_codec_stream_info_t</tt> which will + * be filled with information about the compressed frame. + * + * @return <tt>CODEC_OK</tt> on success, or an error code otherwise. The + * error code can be converted to a <tt>String</tt> with + * {@link VPX#codec_err_to_string(int)} + */ + public static native int codec_peek_stream_info(int iface, + byte[] buf, + int buf_offset, + int buf_size, + long si_ptr); + + /** + * Gets the <tt>sz</tt> field of a <tt>vpx_codec_mmap_t</tt>. + * + * @param mmap Pointer to a <tt>vpx_codec_mmap_t</tt> + * @return The <tt>sz</tt> field of <tt>mmap</tt> + */ + public static native long codec_mmap_get_sz(long mmap); + + /** + * Sets the <tt>base</tt> field of a <tt>vpx_codec_mmap_t</tt> + * + * @param mmap Pointer to a <tt>vpx_codec_mmap_t</tt> + * @param base The value to set. + */ + public static native void codec_mmap_set_base(long mmap, long base); + + + /** + * Allocates memorry on the heap (a simple wrapped around the native + * <tt>malloc()</tt>) + * @param s Number of bytes to allocate + * + * @return Pointer to the memory allocated. + */ + public static native long malloc(long s); + + /** + * Frees memory, which has been allocated with {@link VPX#malloc(long)} or + * one of the <tt>*_malloc()</tt> functions. + * + * @param ptr Pointer to the memory to free. + */ + public static native void free(long ptr); + + /** + * Copies <tt>n</tt> bytes from <tt>src</tt> to <tt>dst</tt>. Simple wrapper + * around the native <tt>memcpy()</tt> funciton. + * + * @param dst Destination. + * @param src Source. + * @param n Number of bytes to copy. + */ + public static native void memcpy(byte[] dst, long src, int n); + + /** + * Fills in <tt>buf</tt> with a string description of the error code + * <tt>err</tt>. Fills at most <tt>buf_size</tt> bytes of <tt>buf</tt> + * + * @param err Error code + * @param buf Buffer to copy the string into + * @param buf_size Buffer size + * + * @return The number of bytes written to <tt>buf</tt> + */ + public static native int codec_err_to_string(int err, + byte[] buf, + int buf_size); + + /** + * Returns a <tt>String</tt> describing the error code <tt>err</tt>. + * @param err Error code + * + * @return A <tt>String</tt> describing the error code <tt>err</tt>. + */ + public static String codec_err_to_string(int err) + { + byte[] buf = new byte[100]; + codec_err_to_string(err, buf, buf.length); + return new String(buf); + } + + + + static + { + System.loadLibrary("jnvpx"); + } + + /** + * Java wrapper around vpx_codec_stream_info_t. Contains basic information, + * obtainable from an encoded frame without a decoder context. + */ + static class StreamInfo + { + /** + * Width + */ + int w; + + /** + * Height + */ + int h; + + /** + * Is keyframe + */ + boolean is_kf; + + /** + * Initializes this instance by parsing <tt>buf</tt> + * + * @param iface Interface, should be one of the <tt>INTERFACE_*</tt> + * constants. + * @param buf Buffer containing a compressed frame to parse. + * @param buf_offset Offset into buffer where the compressed frame + * begins. + * @param buf_size Size of the compressed frame. + */ + StreamInfo(int iface, byte[] buf, int buf_offset, int buf_size) + { + long si = stream_info_malloc(); + + if(codec_peek_stream_info(iface, buf, buf_offset, buf_size, si) + != CODEC_OK) + return; + + w = stream_info_get_w(si); + h = stream_info_get_h(si); + is_kf = stream_info_get_is_kf(si) != 0; + + if(si != 0) + free(si); + } + + /** + * Gets the <tt>w</tt> (width) field of this instance. + * + * @return the <tt>w</tt> (width) field of this instance. + */ + public int getW() + { + return w; + } + + /** + * Gets the <tt>h</tt> (height) field of this instance. + * + * @return the <tt>h</tt> (height) field of this instance. + */ + public int getH() + { + return h; + } + + /** + * Gets the <tt>is_kf</tt> (is keyframe) field of this instance. + * + * @return the <tt>is_kf</tt> (is keyframe) field of this instance. + */ + public boolean isKf() + { + return is_kf; + } + } +} diff --git a/src/org/jitsi/impl/neomedia/codec/video/vp8/VPXDecoder.java b/src/org/jitsi/impl/neomedia/codec/video/vp8/VPXDecoder.java new file mode 100644 index 00000000..405cb609 --- /dev/null +++ b/src/org/jitsi/impl/neomedia/codec/video/vp8/VPXDecoder.java @@ -0,0 +1,355 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package org.jitsi.impl.neomedia.codec.video.vp8; + +import org.jitsi.impl.neomedia.codec.*; +import org.jitsi.impl.neomedia.codec.video.*; +import org.jitsi.service.neomedia.codec.*; +import org.jitsi.util.*; + +import javax.media.*; +import javax.media.format.*; +import java.awt.*; + +/** + * Implements a VP8 decoder. + * + * @author Boris Grozev + */ +public class VPXDecoder + extends AbstractCodecExt +{ + /** + * The <tt>Logger</tt> used by the <tt>VPXDecoder</tt> class + * for logging output. + */ + private static final Logger logger + = Logger.getLogger(VPXDecoder.class); + + /** + * The decoder interface to use + */ + private static final int INTERFACE = VPX.INTEFACE_VP8_DEC; + + /** + * Pointer to the libvpx codec context to be used + */ + private long context = 0; + + /** + * Whether there are unprocessed frames left from a previous call to + * VP8.codec_decode() + */ + private boolean leftoverFrames = false; + + /** + * Iterator for the frames in the decoder context. Can be re-initialized by + * setting it's only element to 0. + */ + private long[] iter = new long[1]; + + /** + * Pointer to a native vpx_image structure, containing a decoded frame. + * When doProcess() is called, this is either 0 or it has the address of + * the next unprocessed image from the decoder + */ + private long img = 0; + + /** + * Pointer to a native vpx_codec_dec_cfg structure containing + * the decoder configuration + */ + private long cfg = 0; + + /** + * The last known height of the video output by this + * <tt>VPXDecoder</tt>. Used to detect changes in the output size. + */ + private int width = Constants.VIDEO_WIDTH; + + /** + * The last known width of the video output by this + * <tt>VPXDecoder</tt>. Used to detect changes in the output size. + */ + private int height = Constants.VIDEO_HEIGHT; + + /** + * Default output formats + */ + private static final VideoFormat[] SUPPORTED_OUTPUT_FORMATS + = new VideoFormat[]{new AVFrameFormat( + new Dimension( + Constants.VIDEO_WIDTH, + Constants.VIDEO_HEIGHT), + Format.NOT_SPECIFIED, + FFmpeg.PIX_FMT_YUV420P, + Format.NOT_SPECIFIED)}; + + /** + * Initializes a new <tt>VPXDecoder</tt> instance. + */ + public VPXDecoder() + { + super("VP8 VPX Decoder", + VideoFormat.class, + SUPPORTED_OUTPUT_FORMATS); + + inputFormat = null; + outputFormat = null; + inputFormats = new VideoFormat[] {new VideoFormat(Constants.VP8)}; + } + + /** + * {@inheritDoc} + */ + protected void doClose() + { + if(logger.isDebugEnabled()) + logger.debug("Closing decoder"); + + if(context != 0) + { + VPX.codec_destroy(context); + VPX.free(context); + } + if(cfg != 0) + VPX.free(cfg); + } + + /** + * {@inheritDoc} + * + * @throws ResourceUnavailableException if initialization failed + */ + protected void doOpen() throws ResourceUnavailableException + { + context = VPX.codec_ctx_malloc(); + //cfg = VPX.codec_dec_cfg_malloc(); + long flags = 0; //VPX.CODEC_USE_XMA; + + int ret = VPX.codec_dec_init(context, INTERFACE, 0, flags); + if(ret != VPX.CODEC_OK) + throw new RuntimeException("Failed to initialize decoder, libvpx" + + " error:\n" + + VPX.codec_err_to_string(ret)); + + if(logger.isDebugEnabled()) + logger.debug("VP8 decoder opened succesfully"); + } + + /** + * {@inheritDoc} + * + * Decodes a VP8 frame contained in <tt>inputBuffer</tt> into + * <tt>outputBuffer</tt> (in <tt>AVFrameFormat</tt>) + * @param inputBuffer input <tt>Buffer</tt> + * @param outputBuffer output <tt>Buffer</tt> + * @return <tt>BUFFER_PROCESSED_OK</tt> if <tt>inBuffer</tt> has been + * successfully processed + */ + protected int doProcess(Buffer inputBuffer, Buffer outputBuffer) + { + if(leftoverFrames) + { + /* + * There are more decoded frames available in the context. Fill + * outputBuffer with the next frame. + */ + updateOutputFormat( + VPX.img_get_d_w(img), + VPX.img_get_d_h(img), + ((VideoFormat) inputBuffer.getFormat()).getFrameRate()); + outputBuffer.setFormat(outputFormat); + + + AVFrame avframe = makeAVFrame(img); + outputBuffer.setData(avframe); + + //YUV420p format , 12 bits per pixel + outputBuffer.setLength(width * height * 3 / 2); + outputBuffer.setTimeStamp(Buffer.TIME_UNKNOWN); + } + else + { + /* + * All frames from the decoder context have been processed. Decode + * the next VP8 frame, and fill outputBuffer with the first decoded + * frame. + */ + + byte[] buf = (byte[])inputBuffer.getData(); + int buf_offset = inputBuffer.getOffset(); + int buf_size = inputBuffer.getLength(); + + int ret = VPX.codec_decode(context, + buf, + buf_offset, + buf_size, + 0, 0); + if(ret != VPX.CODEC_OK) + { + if(logger.isDebugEnabled()) + logger.debug("Discarding a frame, codec_decode() error: " + + VPX.codec_err_to_string(ret)); + outputBuffer.setDiscard(true); + return BUFFER_PROCESSED_OK; + } + + leftoverFrames = false; + iter[0] = 0; //decode has just been called, reset iterator + img = VPX.codec_get_frame(context, iter); + + if(img == 0) + { + outputBuffer.setDiscard(true); + return BUFFER_PROCESSED_OK; + } + + updateOutputFormat( + VPX.img_get_d_w(img), + VPX.img_get_d_h(img), + ((VideoFormat) inputBuffer.getFormat()).getFrameRate()); + outputBuffer.setFormat(outputFormat); + + + AVFrame avframe = makeAVFrame(img); + outputBuffer.setData(avframe); + + //YUV420p format , 12 bits per pixel + outputBuffer.setLength(width * height * 3 / 2); + outputBuffer.setTimeStamp(Buffer.TIME_UNKNOWN); + } + + + /* + * outputBuffer is all setup now. Check the decoder context for more + * decoded frames. + */ + img = VPX.codec_get_frame(context, iter); + if(img == 0) //no more frames + { + leftoverFrames = false; + return BUFFER_PROCESSED_OK; + } + else + { + leftoverFrames = true; + return INPUT_BUFFER_NOT_CONSUMED; + } + } + + /** + * Changes the output format, if necessary, according to the new dimentions + * given via <tt>width</tt> and <tt>height</tt>. + * @param width new width + * @param height new height + * @param frameRate frame rate + */ + private void updateOutputFormat(int width, int height, float frameRate) + { + if ((width > 0) && (height > 0) + && ((this.width != width) || (this.height != height))) + { + this.width = width; + this.height = height; + outputFormat = new AVFrameFormat( + new Dimension(width, height), + frameRate, + FFmpeg.PIX_FMT_YUV420P, + Format.NOT_SPECIFIED); + } + } + + /** + * Allocates a new AVFrame and set it's data fields to the data fields + * from the <tt>vpx_image_t</tt> pointed to by <tt>img</tt>. Also set it's + * 'linesize' according to <tt>img</tt>. + * + * @param img pointer to a <tt>vpx_image_t</tt> whose data will be used + * + * @return an AVFrame instance with it's data fields set to the fields from + * <tt>img</tt> + */ + private AVFrame makeAVFrame(long img) + { + AVFrame avframe = new AVFrame(); + long p0 = VPX.img_get_plane0(img); + long p1 = VPX.img_get_plane1(img); + long p2 = VPX.img_get_plane2(img); + + //p0, p1, p2 are pointers, while avframe_set_data uses offsets + FFmpeg.avframe_set_data(avframe.getPtr(), + p0, + p1-p0, + p2-p1); + + FFmpeg.avframe_set_linesize(avframe.getPtr(), + VPX.img_get_stride0(img), + VPX.img_get_stride1(img), + VPX.img_get_stride2(img)); + + return avframe; + } + + /** + * Get matching outputs for a specified input <tt>Format</tt>. + * + * @param in input <tt>Format</tt> + * @return array of matching outputs or null if there are no matching + * outputs. + */ + protected Format[] getMatchingOutputFormats(Format in) + { + VideoFormat ivf = (VideoFormat) in; + Dimension inSize = ivf.getSize(); + Dimension outSize; + + // return the default size/currently decoder and encoder + // set to transmit/receive at this size + if (inSize == null) + { + VideoFormat ovf = SUPPORTED_OUTPUT_FORMATS[0]; + + if (ovf == null) + return null; + else + outSize = ovf.getSize(); + } + else + outSize = inSize; // Output in same size as input. + + return + new Format[] + { + new AVFrameFormat( + outSize, + ivf.getFrameRate(), + FFmpeg.PIX_FMT_YUV420P, + Format.NOT_SPECIFIED) + }; + } + + /** + * Sets the <tt>Format</tt> of the media data to be input for processing in + * this <tt>Codec</tt>. + * + * @param format the <tt>Format</tt> of the media data to be input for + * processing in this <tt>Codec</tt> + * @return the <tt>Format</tt> of the media data to be input for processing + * in this <tt>Codec</tt> if <tt>format</tt> is compatible with this + * <tt>Codec</tt>; otherwise, <tt>null</tt> + */ + @Override + public Format setInputFormat(Format format) + { + Format setFormat = super.setInputFormat(format); + + if (setFormat != null) + reset(); + return setFormat; + } +} \ No newline at end of file diff --git a/src/org/jitsi/impl/neomedia/codec/video/vp8/VPXEncoder.java b/src/org/jitsi/impl/neomedia/codec/video/vp8/VPXEncoder.java new file mode 100644 index 00000000..06001b52 --- /dev/null +++ b/src/org/jitsi/impl/neomedia/codec/video/vp8/VPXEncoder.java @@ -0,0 +1,459 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package org.jitsi.impl.neomedia.codec.video.vp8; + +import org.jitsi.impl.neomedia.codec.*; +import org.jitsi.impl.neomedia.codec.video.*; +import org.jitsi.service.neomedia.codec.*; +import org.jitsi.util.*; + +import javax.media.*; +import javax.media.format.*; +import java.awt.*; + +/** + * Implements a VP8 encoder. + * + * @author Boris Grozev + */ +public class VPXEncoder + extends AbstractCodecExt +{ + /** + * The <tt>Logger</tt> used by the <tt>VPXEncoder</tt> class and its + * instances for logging output. + */ + private static final Logger logger = Logger.getLogger(VPXEncoder.class); + + /** + * VPX interface to use + */ + private static final int INTERFACE = VPX.INTERFACE_VP8_ENC; + + /** + * Pointer to the libvpx codec context to be used + */ + private long context = 0; + + /** + * Pointer to a native vpx_codec_dec_cfg structure containing + * encoder configuration + */ + private long cfg = 0; + + /** + * Pointer to a native vpx_image instance used to feed frames to the encoder + */ + private long img = 0; + + /** + * Pointer to a vpx_codec_cx_pkt_t + */ + private long pkt = 0; + + /** + * Iterator for the compressed frames in the encoder context. Can be + * re-initialized by setting it's only element to 0. + */ + private long[] iter = new long[1]; + + /** + * Whether there are unprocessed packets left from a previous call to + * VP8.codec_encode() + */ + private boolean leftoverPackets = false; + + /** + * Default output formats + */ + private static final VideoFormat[] SUPPORTED_OUTPUT_FORMATS + = new VideoFormat[] { new VideoFormat(Constants.VP8) }; + + /** + * The frame rate to be assumed by <tt>JNIEncoder</tt> instances in the + * absence of any other frame rate indication. + */ + static final int DEFAULT_FRAME_RATE = 30; + + /** + * Number of encoder frames so far. Used as pst (presentation time stamp) + */ + private long frameCount = 0; + + /** + * Current width of the input and output frames + */ + private int width = Constants.VIDEO_WIDTH; + + /** + * Current height of the input and output frames + */ + private int height = Constants.VIDEO_HEIGHT; + + /** + * Flags passed when (re-)initializing the encoder context + */ + private long flags = 0; + + /** + * Initializes a new <tt>VPXEncoder</tt> instance. + */ + public VPXEncoder() + { + super("VP8 Encoder", + VideoFormat.class, + SUPPORTED_OUTPUT_FORMATS); + inputFormats + = new VideoFormat[] + { + new YUVFormat( + null, + Format.NOT_SPECIFIED, + Format.byteArray, + DEFAULT_FRAME_RATE, + YUVFormat.YUV_420, + Format.NOT_SPECIFIED, Format.NOT_SPECIFIED, + 0, Format.NOT_SPECIFIED, Format.NOT_SPECIFIED) + }; + inputFormat = null; + outputFormat = null; + } + + /** + * {@inheritDoc} + */ + protected void doClose() + { + if(logger.isDebugEnabled()) + logger.debug("Closing encoder"); + if(context != 0) + { + VPX.codec_destroy(context); + VPX.free(context); + context = 0; + } + if(img != 0) + { + VPX.free(img); + img = 0; + } + if(cfg != 0) + { + VPX.free(cfg); + cfg = 0; + } + + + } + + /** + * {@inheritDoc} + * + * @throws ResourceUnavailableException + */ + protected void doOpen() throws ResourceUnavailableException + { + img = VPX.img_malloc(); + if(img == 0) + { + throw new RuntimeException("Could not img_malloc()"); + } + VPX.img_set_fmt(img, VPX.IMG_FMT_I420); + VPX.img_set_bps(img, 12); + + cfg = VPX.codec_enc_cfg_malloc(); + if(cfg == 0) + { + throw new RuntimeException("Could not codec_enc_cfg_malloc()"); + } + VPX.codec_enc_config_default(INTERFACE, cfg, 0); + + //set some settings + VPX.codec_enc_cfg_set_rc_target_bitrate(cfg, 192); + VPX.codec_enc_cfg_set_rc_resize_allowed(cfg, 1); + VPX.codec_enc_cfg_set_rc_end_usage(cfg, VPX.RC_MODE_CBR); + VPX.codec_enc_cfg_set_kf_mode(cfg, VPX.KF_MODE_AUTO); + VPX.codec_enc_cfg_set_w(cfg, width); + VPX.codec_enc_cfg_set_h(cfg, height); + + context = VPX.codec_ctx_malloc(); + int ret = VPX.codec_enc_init(context, INTERFACE, cfg, flags); + + if(ret != VPX.CODEC_OK) + throw new RuntimeException("Failed to initialize encoder, libvpx" + + " error:\n" + + VPX.codec_err_to_string(ret)); + + if (inputFormat == null) + throw new ResourceUnavailableException("No input format selected"); + if (outputFormat == null) + throw new ResourceUnavailableException("No output format selected"); + + if(logger.isDebugEnabled()) + logger.debug("VP8 encoder opened succesfully"); + } + + /** + * {@inheritDoc} + * + * Encodes the frame in <tt>inputBuffer</tt> (in <tt>YUVFormat</tt>) into + * a VP8 frame (in <tt>outputBuffer</tt>) + * + * @param inputBuffer input <tt>Buffer</tt> + * @param outputBuffer output <tt>Buffer</tt> + * + * @return <tt>BUFFER_PROCESSED_OK</tt> if <tt>inBuffer</tt> has been + * successfully processed + */ + protected int doProcess(Buffer inputBuffer, Buffer outputBuffer) + { + if(inputBuffer.isDiscard()) + { + outputBuffer.setDiscard(true); + return BUFFER_PROCESSED_OK; + } + + int ret = BUFFER_PROCESSED_OK; + byte[] output; + if(leftoverPackets) + { + if(VPX.codec_cx_pkt_get_kind(pkt) == VPX.CODEC_CX_FRAME_PKT) + { + int size = VPX.codec_cx_pkt_get_size(pkt); + output = validateByteArraySize(inputBuffer, size); + VPX.memcpy(output, + VPX.codec_cx_pkt_get_data(pkt), + size); + outputBuffer.setOffset(0); + outputBuffer.setLength(size); + outputBuffer.setTimeStamp(inputBuffer.getTimeStamp()); + } + else + { + //not a compressed frame, skip this packet + ret |= OUTPUT_BUFFER_NOT_FILLED; + } + } + else + { + frameCount++; + + YUVFormat format = (YUVFormat) inputBuffer.getFormat(); + int width = (int) format.getSize().getWidth(); + int height = (int) format.getSize().getHeight(); + + if (width > 0 && height > 0 && + (width != this.width || height != this.height)) + { + if(logger.isInfoEnabled()) + logger.info("Setting new width/height: "+width + "/" + + height); + this.width = width; + this.height = height; + VPX.img_set_w(img, width); + VPX.img_set_d_w(img, width); + VPX.img_set_h(img, height); + VPX.img_set_d_h(img, height); + VPX.codec_enc_cfg_set_w(cfg, width); + VPX.codec_enc_cfg_set_h(cfg, height); + reinit(); + } + + //setup img + int strideY = format.getStrideY(); + if (strideY == Format.NOT_SPECIFIED) + strideY = width; + int strideUV = format.getStrideUV(); + if (strideUV == Format.NOT_SPECIFIED) + strideUV = width/2; + VPX.img_set_stride0(img, strideY); + VPX.img_set_stride1(img, strideUV); + VPX.img_set_stride2(img, strideUV); + VPX.img_set_stride3(img, 0); + + int offsetY = format.getOffsetY(); + if (offsetY == Format.NOT_SPECIFIED) + offsetY = 0; + int offsetU = format.getOffsetU(); + if (offsetU == Format.NOT_SPECIFIED) + offsetU = offsetY + width * height; + int offsetV = format.getOffsetV(); + if (offsetV == Format.NOT_SPECIFIED) + offsetV = offsetU + (width * height) / 4; + + int result = VPX.codec_encode( + context, + img, + (byte[]) inputBuffer.getData(), + offsetY, + offsetU, + offsetV, + frameCount, //pts + 1, //duration + 0, //flags + VPX.DL_REALTIME); + if(result != VPX.CODEC_OK) + { + logger.warn("Failed to encode a frame: " + + VPX.codec_err_to_string(result)); + outputBuffer.setDiscard(true); + return BUFFER_PROCESSED_OK; + } + + iter[0] = 0; + pkt = VPX.codec_get_cx_data(context, iter); + if(pkt != 0 && + VPX.codec_cx_pkt_get_kind(pkt) == VPX.CODEC_CX_FRAME_PKT) + { + int size = VPX.codec_cx_pkt_get_size(pkt); + long data = VPX.codec_cx_pkt_get_data(pkt); + output = validateByteArraySize(outputBuffer, size); + VPX.memcpy(output, data, size); + outputBuffer.setOffset(0); + outputBuffer.setLength(size); + outputBuffer.setTimeStamp(inputBuffer.getTimeStamp()); + } + else + { + //not a compressed frame, skip this packet + ret |= OUTPUT_BUFFER_NOT_FILLED; + } + } + + pkt = VPX.codec_get_cx_data(context, iter); + leftoverPackets = pkt != 0; + + if(leftoverPackets) + return ret | INPUT_BUFFER_NOT_CONSUMED; + else + return ret; + + } + + /** + * Reinitializes the encoder context. Needed in order to encode frames + * with different width or height + */ + private void reinit() + { + VPX.codec_destroy(context); + + int ret = VPX.codec_enc_init(context, INTERFACE, cfg, flags); + + if(ret != VPX.CODEC_OK) + throw new RuntimeException("Failed to re-initialize encoder, libvpx" + + " error:\n" + + VPX.codec_err_to_string(ret)); + } + + /** + * Sets the input format. + * + * @param in format to set + * @return format + */ + @Override + public Format setInputFormat(Format in) + { + if(!(in instanceof VideoFormat) || (matches(in, inputFormats) == null)) + return null; + + YUVFormat yuv = (YUVFormat) in; + + if (yuv.getOffsetU() > yuv.getOffsetV()) + return null; + Dimension size = yuv.getSize(); + + if (size == null) + size = new Dimension(Constants.VIDEO_WIDTH, Constants.VIDEO_HEIGHT); + + int strideY = size.width; + int strideUV = strideY / 2; + int offsetU = strideY * size.height; + int offsetV = offsetU + strideUV * size.height / 2; + + int yuvMaxDataLength = (strideY + strideUV) * size.height; + + inputFormat + = new YUVFormat( + size, + yuvMaxDataLength + FFmpeg.FF_INPUT_BUFFER_PADDING_SIZE, + Format.byteArray, + yuv.getFrameRate(), + YUVFormat.YUV_420, + strideY, strideUV, + 0, offsetU, offsetV); + + // Return the selected inputFormat + return inputFormat; + } + + /** + * Sets the <tt>Format</tt> in which this <tt>Codec</tt> is to output media + * data. + * + * @param out the <tt>Format</tt> in which this <tt>Codec</tt> is to + * output media data + * @return the <tt>Format</tt> in which this <tt>Codec</tt> is currently + * configured to output media data or <tt>null</tt> if <tt>format</tt> was + * found to be incompatible with this <tt>Codec</tt> + */ + @Override + public Format setOutputFormat(Format out) + { + if(!(out instanceof VideoFormat) || + (matches(out, getMatchingOutputFormats(inputFormat)) == null)) + return null; + + VideoFormat videoOut = (VideoFormat) out; + Dimension outSize = videoOut.getSize(); + + if (outSize == null) + { + Dimension inSize = ((VideoFormat) inputFormat).getSize(); + + outSize + = (inSize == null) + ? new Dimension( + Constants.VIDEO_WIDTH, + Constants.VIDEO_HEIGHT) + : inSize; + } + + outputFormat = new VideoFormat( + videoOut.getEncoding(), + outSize, + Format.NOT_SPECIFIED, + Format.byteArray, + videoOut.getFrameRate()); + + // Return the selected outputFormat + return outputFormat; + } + + /** + * Gets the matching output formats for a specific format. + * + * @param in input format + * @return array of formats matching input format + */ + protected Format[] getMatchingOutputFormats(Format in) + { + VideoFormat videoIn = (VideoFormat) in; + + return + new VideoFormat[] + { + new VideoFormat( + Constants.VP8, + videoIn.getSize(), + Format.NOT_SPECIFIED, + Format.byteArray, + videoIn.getFrameRate()) + }; + } +} -- GitLab