Skip to content

Commit

Permalink
merge official 9.5.8
Browse files Browse the repository at this point in the history
  • Loading branch information
luvletter2333 committed Apr 4, 2023
2 parents 096ea57 + 683c4e6 commit 3bc1326
Show file tree
Hide file tree
Showing 64 changed files with 1,619 additions and 610 deletions.
8 changes: 4 additions & 4 deletions TMessagesProj/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import cn.hutool.core.util.RuntimeUtil
apply plugin: "com.android.application"
apply plugin: "kotlin-android"

def verName = "9.5.6-preview02"
def verCode = 726
def verName = "9.5.8-preview01"
def verCode = 730

if (System.getenv("DEBUG_BUILD") == "true") {
verName += "-" + RuntimeUtil.execForStr("git log --pretty=format:'%h' -n 1").trim().replace('\'','')
}

def officialVer = "9.5.6"
def officialCode = 3237
def officialVer = "9.5.8"
def officialCode = 3252

def serviceAccountCredentialsFile = rootProject.file("service_account_credentials.json")

Expand Down
2 changes: 1 addition & 1 deletion TMessagesProj/jni/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ target_include_directories(breakpad PUBLIC
#voip
include(${CMAKE_HOME_DIRECTORY}/voip/CMakeLists.txt)

set(NATIVE_LIB "tmessages.43")
set(NATIVE_LIB "tmessages.44")

#tmessages
add_library(${NATIVE_LIB} SHARED
Expand Down
169 changes: 91 additions & 78 deletions TMessagesProj/jni/exoplayer/ffmpeg_jni.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,47 +13,48 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <android/log.h>
#include <jni.h>
#include <stdlib.h>
#include <android/log.h>

extern "C" {
#ifdef __cplusplus
#define __STDC_CONSTANT_MACROS
#ifdef _STDINT_H
#undef _STDINT_H
#endif
#include <stdint.h>
#endif
#include <libavcodec/avcodec.h>
#include <libavresample/avresample.h>
#include <libavutil/channel_layout.h>
#include <libavutil/error.h>
#include <libavutil/opt.h>
#include <libswresample/swresample.h>
}

#define LOG_TAG "ffmpeg_jni"
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, \
__VA_ARGS__))

#define DECODER_FUNC(RETURN_TYPE, NAME, ...) \
extern "C" { \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegDecoder_ ## NAME \
(JNIEnv* env, jobject thiz, ##__VA_ARGS__);\
} \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegDecoder_ ## NAME \
(JNIEnv* env, jobject thiz, ##__VA_ARGS__)\

#define LIBRARY_FUNC(RETURN_TYPE, NAME, ...) \
extern "C" { \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegLibrary_ ## NAME \
(JNIEnv* env, jobject thiz, ##__VA_ARGS__);\
} \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegLibrary_ ## NAME \
(JNIEnv* env, jobject thiz, ##__VA_ARGS__)\
#define LOGE(...) \
((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))

#define LIBRARY_FUNC(RETURN_TYPE, NAME, ...) \
extern "C" { \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegLibrary_##NAME( \
JNIEnv *env, jobject thiz, ##__VA_ARGS__); \
} \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegLibrary_##NAME( \
JNIEnv *env, jobject thiz, ##__VA_ARGS__)

#define AUDIO_DECODER_FUNC(RETURN_TYPE, NAME, ...) \
extern "C" { \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegAudioDecoder_##NAME( \
JNIEnv *env, jobject thiz, ##__VA_ARGS__); \
} \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegAudioDecoder_##NAME( \
JNIEnv *env, jobject thiz, ##__VA_ARGS__)

#define ERROR_STRING_BUFFER_LENGTH 256

Expand All @@ -62,14 +63,13 @@ static const AVSampleFormat OUTPUT_FORMAT_PCM_16BIT = AV_SAMPLE_FMT_S16;
// Output format corresponding to AudioFormat.ENCODING_PCM_FLOAT.
static const AVSampleFormat OUTPUT_FORMAT_PCM_FLOAT = AV_SAMPLE_FMT_FLT;

// Error codes matching FfmpegDecoder.java.
static const int DECODER_ERROR_INVALID_DATA = -1;
static const int DECODER_ERROR_OTHER = -2;
static const int AUDIO_DECODER_ERROR_INVALID_DATA = -1;
static const int AUDIO_DECODER_ERROR_OTHER = -2;

/**
* Returns the AVCodec with the specified name, or NULL if it is not available.
*/
AVCodec *getCodecByName(JNIEnv* env, jstring codecName);
AVCodec *getCodecByName(JNIEnv *env, jstring codecName);

/**
* Allocates and opens a new AVCodecContext for the specified codec, passing the
Expand All @@ -82,11 +82,17 @@ AVCodecContext *createContext(JNIEnv *env, AVCodec *codec, jbyteArray extraData,

/**
* Decodes the packet into the output buffer, returning the number of bytes
* written, or a negative DECODER_ERROR constant value in the case of an error.
* written, or a negative AUDIO_DECODER_ERROR constant value in the case of an
* error.
*/
int decodePacket(AVCodecContext *context, AVPacket *packet,
uint8_t *outputBuffer, int outputSize);

/**
* Transforms ffmpeg AVERROR into a negative AUDIO_DECODER_ERROR constant value.
*/
int transformError(int errorNumber);

/**
* Outputs a log message describing the avcodec error number.
*/
Expand All @@ -101,12 +107,17 @@ LIBRARY_FUNC(jstring, ffmpegGetVersion) {
return env->NewStringUTF(LIBAVCODEC_IDENT);
}

LIBRARY_FUNC(jint, ffmpegGetInputBufferPaddingSize) {
return (jint)AV_INPUT_BUFFER_PADDING_SIZE;
}

LIBRARY_FUNC(jboolean, ffmpegHasDecoder, jstring codecName) {
return getCodecByName(env, codecName) != NULL;
}

DECODER_FUNC(jlong, ffmpegInitialize, jstring codecName, jbyteArray extraData,
jboolean outputFloat, jint rawSampleRate, jint rawChannelCount) {
AUDIO_DECODER_FUNC(jlong, ffmpegInitialize, jstring codecName,
jbyteArray extraData, jboolean outputFloat,
jint rawSampleRate, jint rawChannelCount) {
AVCodec *codec = getCodecByName(env, codecName);
if (!codec) {
LOGE("Codec not found.");
Expand All @@ -116,8 +127,8 @@ DECODER_FUNC(jlong, ffmpegInitialize, jstring codecName, jbyteArray extraData,
rawChannelCount);
}

DECODER_FUNC(jint, ffmpegDecode, jlong context, jobject inputData,
jint inputSize, jobject outputData, jint outputSize) {
AUDIO_DECODER_FUNC(jint, ffmpegDecode, jlong context, jobject inputData,
jint inputSize, jobject outputData, jint outputSize) {
if (!context) {
LOGE("Context must be non-NULL.");
return -1;
Expand All @@ -134,34 +145,34 @@ DECODER_FUNC(jint, ffmpegDecode, jlong context, jobject inputData,
LOGE("Invalid output buffer length: %d", outputSize);
return -1;
}
uint8_t *inputBuffer = (uint8_t *) env->GetDirectBufferAddress(inputData);
uint8_t *outputBuffer = (uint8_t *) env->GetDirectBufferAddress(outputData);
uint8_t *inputBuffer = (uint8_t *)env->GetDirectBufferAddress(inputData);
uint8_t *outputBuffer = (uint8_t *)env->GetDirectBufferAddress(outputData);
AVPacket packet;
av_init_packet(&packet);
packet.data = inputBuffer;
packet.size = inputSize;
return decodePacket((AVCodecContext *) context, &packet, outputBuffer,
return decodePacket((AVCodecContext *)context, &packet, outputBuffer,
outputSize);
}

DECODER_FUNC(jint, ffmpegGetChannelCount, jlong context) {
AUDIO_DECODER_FUNC(jint, ffmpegGetChannelCount, jlong context) {
if (!context) {
LOGE("Context must be non-NULL.");
return -1;
}
return ((AVCodecContext *) context)->channels;
return ((AVCodecContext *)context)->channels;
}

DECODER_FUNC(jint, ffmpegGetSampleRate, jlong context) {
AUDIO_DECODER_FUNC(jint, ffmpegGetSampleRate, jlong context) {
if (!context) {
LOGE("Context must be non-NULL.");
return -1;
}
return ((AVCodecContext *) context)->sample_rate;
return ((AVCodecContext *)context)->sample_rate;
}

DECODER_FUNC(jlong, ffmpegReset, jlong jContext, jbyteArray extraData) {
AVCodecContext *context = (AVCodecContext *) jContext;
AUDIO_DECODER_FUNC(jlong, ffmpegReset, jlong jContext, jbyteArray extraData) {
AVCodecContext *context = (AVCodecContext *)jContext;
if (!context) {
LOGE("Tried to reset without a context.");
return 0L;
Expand All @@ -178,23 +189,23 @@ DECODER_FUNC(jlong, ffmpegReset, jlong jContext, jbyteArray extraData) {
return 0L;
}
jboolean outputFloat =
(jboolean)(context->request_sample_fmt == OUTPUT_FORMAT_PCM_FLOAT);
(jboolean)(context->request_sample_fmt == OUTPUT_FORMAT_PCM_FLOAT);
return (jlong)createContext(env, codec, extraData, outputFloat,
/* rawSampleRate= */ -1,
/* rawChannelCount= */ -1);
/* rawSampleRate= */ -1,
/* rawChannelCount= */ -1);
}

avcodec_flush_buffers(context);
return (jlong) context;
return (jlong)context;
}

DECODER_FUNC(void, ffmpegRelease, jlong context) {
AUDIO_DECODER_FUNC(void, ffmpegRelease, jlong context) {
if (context) {
releaseContext((AVCodecContext *) context);
releaseContext((AVCodecContext *)context);
}
}

AVCodec *getCodecByName(JNIEnv* env, jstring codecName) {
AVCodec *getCodecByName(JNIEnv *env, jstring codecName) {
if (!codecName) {
return NULL;
}
Expand All @@ -213,18 +224,18 @@ AVCodecContext *createContext(JNIEnv *env, AVCodec *codec, jbyteArray extraData,
return NULL;
}
context->request_sample_fmt =
outputFloat ? OUTPUT_FORMAT_PCM_FLOAT : OUTPUT_FORMAT_PCM_16BIT;
outputFloat ? OUTPUT_FORMAT_PCM_FLOAT : OUTPUT_FORMAT_PCM_16BIT;
if (extraData) {
jsize size = env->GetArrayLength(extraData);
context->extradata_size = size;
context->extradata =
(uint8_t *) av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
(uint8_t *)av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
if (!context->extradata) {
LOGE("Failed to allocate extradata.");
releaseContext(context);
return NULL;
}
env->GetByteArrayRegion(extraData, 0, size, (jbyte *) context->extradata);
env->GetByteArrayRegion(extraData, 0, size, (jbyte *)context->extradata);
}
if (context->codec_id == AV_CODEC_ID_PCM_MULAW ||
context->codec_id == AV_CODEC_ID_PCM_ALAW) {
Expand All @@ -249,8 +260,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
result = avcodec_send_packet(context, packet);
if (result) {
logError("avcodec_send_packet", result);
return result == AVERROR_INVALIDDATA ? DECODER_ERROR_INVALID_DATA
: DECODER_ERROR_OTHER;
return transformError(result);
}

// Dequeue output data until it runs out.
Expand All @@ -259,7 +269,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
AVFrame *frame = av_frame_alloc();
if (!frame) {
LOGE("Failed to allocate output frame.");
return -1;
return AUDIO_DECODER_ERROR_INVALID_DATA;
}
result = avcodec_receive_frame(context, frame);
if (result) {
Expand All @@ -268,7 +278,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
break;
}
logError("avcodec_receive_frame", result);
return result;
return transformError(result);
}

// Resample output.
Expand All @@ -279,59 +289,63 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
int sampleCount = frame->nb_samples;
int dataSize = av_samples_get_buffer_size(NULL, channelCount, sampleCount,
sampleFormat, 1);
AVAudioResampleContext *resampleContext;
SwrContext *resampleContext;
if (context->opaque) {
resampleContext = (AVAudioResampleContext *) context->opaque;
resampleContext = (SwrContext *)context->opaque;
} else {
resampleContext = avresample_alloc_context();
av_opt_set_int(resampleContext, "in_channel_layout", channelLayout, 0);
resampleContext = swr_alloc();
av_opt_set_int(resampleContext, "in_channel_layout", channelLayout, 0);
av_opt_set_int(resampleContext, "out_channel_layout", channelLayout, 0);
av_opt_set_int(resampleContext, "in_sample_rate", sampleRate, 0);
av_opt_set_int(resampleContext, "out_sample_rate", sampleRate, 0);
av_opt_set_int(resampleContext, "in_sample_fmt", sampleFormat, 0);
// The output format is always the requested format.
av_opt_set_int(resampleContext, "out_sample_fmt",
context->request_sample_fmt, 0);
result = avresample_open(resampleContext);
context->request_sample_fmt, 0);
result = swr_init(resampleContext);
if (result < 0) {
logError("avresample_open", result);
logError("swr_init", result);
av_frame_free(&frame);
return -1;
return transformError(result);
}
context->opaque = resampleContext;
}
int inSampleSize = av_get_bytes_per_sample(sampleFormat);
int outSampleSize = av_get_bytes_per_sample(context->request_sample_fmt);
int outSamples = avresample_get_out_samples(resampleContext, sampleCount);
int outSamples = swr_get_out_samples(resampleContext, sampleCount);
int bufferOutSize = outSampleSize * channelCount * outSamples;
if (outSize + bufferOutSize > outputSize) {
LOGE("Output buffer size (%d) too small for output data (%d).",
outputSize, outSize + bufferOutSize);
av_frame_free(&frame);
return -1;
return AUDIO_DECODER_ERROR_INVALID_DATA;
}
result = avresample_convert(resampleContext, &outputBuffer, bufferOutSize,
outSamples, frame->data, frame->linesize[0],
sampleCount);
result = swr_convert(resampleContext, &outputBuffer, bufferOutSize,
(const uint8_t **)frame->data, frame->nb_samples);
av_frame_free(&frame);
if (result < 0) {
logError("avresample_convert", result);
return result;
logError("swr_convert", result);
return AUDIO_DECODER_ERROR_INVALID_DATA;
}
int available = avresample_available(resampleContext);
int available = swr_get_out_samples(resampleContext, 0);
if (available != 0) {
LOGE("Expected no samples remaining after resampling, but found %d.",
available);
return -1;
return AUDIO_DECODER_ERROR_INVALID_DATA;
}
outputBuffer += bufferOutSize;
outSize += bufferOutSize;
}
return outSize;
}

int transformError(int errorNumber) {
return errorNumber == AVERROR_INVALIDDATA ? AUDIO_DECODER_ERROR_INVALID_DATA
: AUDIO_DECODER_ERROR_OTHER;
}

void logError(const char *functionName, int errorNumber) {
char *buffer = (char *) malloc(ERROR_STRING_BUFFER_LENGTH * sizeof(char));
char *buffer = (char *)malloc(ERROR_STRING_BUFFER_LENGTH * sizeof(char));
av_strerror(errorNumber, buffer, ERROR_STRING_BUFFER_LENGTH);
LOGE("Error in %s: %s", functionName, buffer);
free(buffer);
Expand All @@ -341,11 +355,10 @@ void releaseContext(AVCodecContext *context) {
if (!context) {
return;
}
AVAudioResampleContext *resampleContext;
if ((resampleContext = (AVAudioResampleContext *) context->opaque)) {
avresample_free(&resampleContext);
SwrContext *swrContext;
if ((swrContext = (SwrContext *)context->opaque)) {
swr_free(&swrContext);
context->opaque = NULL;
}
avcodec_free_context(&context);
}

0 comments on commit 3bc1326

Please sign in to comment.