android把h264 acc保存为ts文件
时间: 2024-03-10 17:46:33 浏览: 215
要在 Android 上使用 FFmpeg 将 H.264 和 AAC 流保存为 TS 文件,你需要将 FFmpeg 编译为 Android 平台上的静态库,并在你的应用程序中使用它。
以下是一个使用 FFmpeg 在 Android 上将 H.264 和 AAC 流保存为 TS 文件的示例代码:
```java
import java.io.IOException;
public class FFmpegConverter {
static {
System.loadLibrary("ffmpeg");
}
public native int convertToTS(String inputFilePath, String outputFilePath);
public void convert(String inputFilePath, String outputFilePath) throws IOException {
int result = convertToTS(inputFilePath, outputFilePath);
if (result != 0) {
throw new IOException("Failed to convert to TS: " + result);
}
}
}
```
在上面的代码中,`convertToTS()` 方法使用 JNI 调用 FFmpeg 库来执行转换操作。以下是 `convertToTS()` 方法的实现:
```c
#include <jni.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "libavutil/opt.h"
#include "libavutil/samplefmt.h"
#include "libavformat/avformat.h"
#include "libswresample/swresample.h"
#include "libavcodec/avcodec.h"
JNIEXPORT jint JNICALL
Java_com_example_ffmpegconverter_FFmpegConverter_convertToTS(JNIEnv *env, jobject thiz,
jstring input_file_path,
jstring output_file_path) {
const char *input_path = (*env)->GetStringUTFChars(env, input_file_path, 0);
const char *output_path = (*env)->GetStringUTFChars(env, output_file_path, 0);
AVFormatContext *input_format_context = NULL;
int ret = avformat_open_input(&input_format_context, input_path, NULL, NULL);
if (ret < 0) {
goto end;
}
ret = avformat_find_stream_info(input_format_context, NULL);
if (ret < 0) {
goto end;
}
AVFormatContext *output_format_context = NULL;
ret = avformat_alloc_output_context2(&output_format_context, NULL, "mpegts", output_path);
if (ret < 0) {
goto end;
}
for (int i = 0; i < input_format_context->nb_streams; i++) {
AVStream *input_stream = input_format_context->streams[i];
AVCodecParameters *input_codec_parameters = input_stream->codecpar;
AVCodec *input_codec = avcodec_find_decoder(input_codec_parameters->codec_id);
if (!input_codec) {
goto end;
}
AVStream *output_stream = avformat_new_stream(output_format_context, input_codec);
if (!output_stream) {
goto end;
}
ret = avcodec_parameters_copy(output_stream->codecpar, input_codec_parameters);
if (ret < 0) {
goto end;
}
output_stream->codecpar->codec_tag = 0;
if (output_format_context->oformat->flags & AVFMT_GLOBALHEADER) {
output_stream->codecpar->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
}
ret = avio_open(&output_format_context->pb, output_path, AVIO_FLAG_WRITE);
if (ret < 0) {
goto end;
}
ret = avformat_write_header(output_format_context, NULL);
if (ret < 0) {
goto end;
}
AVPacket packet;
av_init_packet(&packet);
while (av_read_frame(input_format_context, &packet) == 0) {
AVStream *input_stream = input_format_context->streams[packet.stream_index];
AVStream *output_stream = output_format_context->streams[packet.stream_index];
packet.pts = av_rescale_q_rnd(packet.pts, input_stream->time_base, output_stream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
packet.dts = av_rescale_q_rnd(packet.dts, input_stream->time_base, output_stream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
packet.duration = av_rescale_q(packet.duration, input_stream->time_base, output_stream->time_base);
packet.pos = -1;
ret = av_interleaved_write_frame(output_format_context, &packet);
if (ret < 0) {
goto end;
}
av_packet_unref(&packet);
}
ret = av_write_trailer(output_format_context);
if (ret < 0) {
goto end;
}
end:
if (output_format_context) {
avio_closep(&output_format_context->pb);
avformat_free_context(output_format_context);
}
if (input_format_context) {
avformat_close_input(&input_format_context);
}
(*env)->ReleaseStringUTFChars(env, input_file_path, input_path);
(*env)->ReleaseStringUTFChars(env, output_file_path, output_path);
return ret;
}
```
在 `convertToTS()` 方法中,我们首先打开输入文件并读取流信息,然后创建一个输出格式上下文和输出流,并将输入流的编解码参数复制到输出流中。然后我们打开输出文件并写入头部信息,接着从输入文件中读取数据包,并将其转换为输出流的时间基。最后,我们将包写入输出文件,并在完成后写入尾部信息。
编译 FFmpeg 静态库的详细步骤超出了本回答的范围,但你可以参考一些在线资源,例如 FFmpeg 官方文档和博客,以帮助你完成此任务。
阅读全文