#include <jni.h> #include <android/log.h> #include <media/NdkMediaCodec.h> #include <media/NdkMediaFormat.h>

// Function to decode and encode a video using Android's MediaCodec and AMediaFormat void decodeAndEncodeVideo(const char *inputFile, const char *outputFile) { // Initialize AMediaFormat for input format AMediaFormat *inputFormat = AMediaFormat_new(); AMediaFormat_setString(inputFormat, AMEDIAFORMAT_KEY_MIME, "video/avc"); AMediaFormat_setInt32(inputFormat, AMEDIAFORMAT_KEY_WIDTH, 640); // Replace with actual width AMediaFormat_setInt32(inputFormat, AMEDIAFORMAT_KEY_HEIGHT, 480); // Replace with actual height

// Initialize AMediaFormat for output format
AMediaFormat *outputFormat = AMediaFormat_new();
AMediaFormat_setString(outputFormat, AMEDIAFORMAT_KEY_MIME, "video/avc");
AMediaFormat_setInt32(outputFormat, AMEDIAFORMAT_KEY_WIDTH, 640); // Replace with desired output width
AMediaFormat_setInt32(outputFormat, AMEDIAFORMAT_KEY_HEIGHT, 480); // Replace with desired output height
AMediaFormat_setInt32(outputFormat, AMEDIAFORMAT_KEY_BIT_RATE, 400000); // Replace with desired bit rate
AMediaFormat_setInt32(outputFormat, AMEDIAFORMAT_KEY_FRAME_RATE, 30); // Replace with desired frame rate

// Create MediaCodec for decoding
AMediaCodec *decoder = AMediaCodec_createDecoderByType("video/avc");
AMediaCodec_configure(decoder, inputFormat, nullptr, nullptr, 0);
AMediaCodec_start(decoder);

// Create MediaCodec for encoding
AMediaCodec *encoder = AMediaCodec_createEncoderByType("video/avc");
AMediaCodec_configure(encoder, outputFormat, nullptr, nullptr, AMEDIACODEC_CONFIGURE_FLAG_ENCODE);
AMediaCodec_start(encoder);

// Open input file for reading
FILE *inputFd = fopen(inputFile, "rb");
if (!inputFd) {
    __android_log_print(ANDROID_LOG_ERROR, "VideoProcessing", "Error opening input file: %s", inputFile);
    return;
}

// Open output file for writing
FILE *outputFd = fopen(outputFile, "wb");
if (!outputFd) {
    __android_log_print(ANDROID_LOG_ERROR, "VideoProcessing", "Error opening output file: %s", outputFile);
    fclose(inputFd);
    return;
}

// Read and process input frames
ssize_t readBytes;
uint8_t *inputBuffer = nullptr;
ssize_t inputBufferSize = 0;
int inputFrameIndex = 0;

while ((readBytes = fread(inputBuffer, 1, inputBufferSize, inputFd)) > 0) {
    // Create input buffer for decoding
    ssize_t inputIndex = AMediaCodec_dequeueInputBuffer(decoder, -1);
    if (inputIndex >= 0) {
        size_t inputSize;
        uint8_t *inputBuffer = AMediaCodec_getInputBuffer(decoder, inputIndex, &inputSize);
        memcpy(inputBuffer, inputBuffer, readBytes);
        AMediaCodec_queueInputBuffer(decoder, inputIndex, 0, readBytes, 0);
    }

    // Dequeue and process decoded output frame
    AMediaCodecBufferInfo info;
    ssize_t outputIndex = AMediaCodec_dequeueOutputBuffer(decoder, &info, 0);
    if (outputIndex >= 0) {
        // Get decoded frame data
        size_t outputSize;
        uint8_t *outputBuffer = AMediaCodec_getOutputBuffer(decoder, outputIndex, &outputSize);
        
        // Encode the decoded frame
        ssize_t encodeIndex = AMediaCodec_dequeueInputBuffer(encoder, -1);
        if (encodeIndex >= 0) {
            size_t encodeSize;
            uint8_t *encodeBuffer = AMediaCodec_getInputBuffer(encoder, encodeIndex, &encodeSize);
            memcpy(encodeBuffer, outputBuffer, info.size);
            AMediaCodec_queueInputBuffer(encoder, encodeIndex, 0, info.size, 0);
        }

        // Get encoded output frame
        AMediaCodecBufferInfo encodeInfo;
        ssize_t encodeOutputIndex = AMediaCodec_dequeueOutputBuffer(encoder, &encodeInfo, 0);
        if (encodeOutputIndex >= 0) {
            // Write encoded frame to output file
            uint8_t *encodeOutputBuffer = AMediaCodec_getOutputBuffer(encoder, encodeOutputIndex, nullptr);
            fwrite(encodeOutputBuffer, 1, encodeInfo.size, outputFd);
            AMediaCodec_releaseOutputBuffer(encoder, encodeOutputIndex, false);
        }

        AMediaCodec_releaseOutputBuffer(decoder, outputIndex, false);
    }
}

// Clean up
fclose(inputFd);
fclose(outputFd);
AMediaCodec_stop(decoder);
AMediaCodec_delete(decoder);
AMediaCodec_stop(encoder);
AMediaCodec_delete(encoder);
AMediaFormat_delete(inputFormat);
AMediaFormat_delete(outputFormat);

}

extern "C" JNIEXPORT void JNICALL Java_com_example_videoprocessing_MainActivity_processVideo( JNIEnv env, jobject / this */, jstring inputFile, jstring outputFile) { const char *inputFileCStr = env->GetStringUTFChars(inputFile, nullptr); const char *outputFileCStr = env->GetStringUTFChars(outputFile, nullptr);

// Call decodeAndEncodeVideo function
decodeAndEncodeVideo(inputFileCStr, outputFileCStr);

env->ReleaseStringUTFChars(inputFile, inputFileCStr);
env->ReleaseStringUTFChars(outputFile, outputFileCStr);

}