具体代码请看:NDKPractice项目的ffmpeg83
1.解决内存上涨的问题
将循环中新建数组操作提到循环外面去
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
jbyteArray jPcmByteArray = env->NewByteArray(dataSize);
// native 创建 c 数组
jbyte *jPcmData = env->GetByteArrayElements(jPcmByteArray, NULL);
pPacket = av_packet_alloc();
pFrame = av_frame_alloc();
// 循环从上下文中读取帧到包中
while (av_read_frame(pFormatContext, pPacket) >= 0) {
if (pPacket->stream_index == audioStreamIndex) {
// Packet 包,压缩的数据,解码成 pcm 数据
int codecSendPacketRes = avcodec_send_packet(pCodecContext, pPacket);
if (codecSendPacketRes == 0) {
int codecReceiveFrameRes = avcodec_receive_frame(pCodecContext, pFrame);
if (codecReceiveFrameRes == 0) {
// AVPacket -> AVFrame
index++;
LOGE("解码第 %d 帧", index);
// 调用重采样的方法
swr_convert(swrContext, &resampleOutBuffer, pFrame->nb_samples,
(const uint8_t **) pFrame->data, pFrame->nb_samples);
// write 写到缓冲区 pFrame.data -> javabyte
// size 是多大,装 pcm 的数据
// 1s 44100 点,2通道, 2字节 44100*2*2
// 1帧不是一秒,pFrame->nb_samples点
memcpy(jPcmData, resampleOutBuffer, dataSize);
// 1 把 c 的数组的数据同步到 jbyteArray,然后不释放native数组
env->ReleaseByteArrayElements(jPcmByteArray, jPcmData, JNI_COMMIT);
pJniCall->callAudioTrackWrite(jPcmByteArray, 0, dataSize);
}
}
}
// 解引用
av_packet_unref(pPacket);
av_frame_unref(pFrame);
}
// 1.解引用数据 data, 2.销魂 pPacket 结构体内存, 3.pPacket = NULL;
av_packet_free(&pPacket);
av_frame_free(&pFrame);
// 0 把 c 的数组的数据同步到 jbyteArray,然后释放native数组
env->ReleaseByteArrayElements(jPcmByteArray, jPcmData, 0);
// 解除 jPcmDataArray 的持有,让 javaGC 回收
env->DeleteLocalRef(jPcmByteArray);
2.解决杂音问题
分析
- 原因:是因为音频的的采样率和采用格式跟我们使用AudioTrack播放设置的会不一致。
- 解决:使用重采样
1 | // --------------- 重采样 start -------------- |
3. 添加错误回调到 Java
1 |
|
4.多线程解码播放
1 | void *threadPlay(void *arg) { |
5.ffmpeg的一些常用指令
1 | ffmpeg 命令 |
问题:子线程中返回 java 错误会有问题