mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2026-06-14 20:15:58 +08:00
增加FFmpegEncoder和test_audio_transcode, 主要修改有:
- 使用FFmpegAudioFifo来简化代码 - 修复转码时间戳不规则递增,导致的音频破音和不连续问题 - 使用double来保存_tsp,避免出现2.5ms的frame_size(ffmpeg内置的opus)
This commit is contained in:
118
tests/test_audio_transcode.cpp
Normal file
118
tests/test_audio_transcode.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
#include "Codec/Transcode.h"
|
||||
#include "Record/MP4Demuxer.h"
|
||||
#include "Record/MP4Muxer.h"
|
||||
#include "Extension/AAC.h"
|
||||
#include "Extension/Opus.h"
|
||||
#include "Extension/G711.h"
|
||||
#include "Util/logger.h"
|
||||
using namespace mediakit;
|
||||
struct TransCtx {
|
||||
using Ptr = std::shared_ptr<TransCtx>;
|
||||
TransCtx(const char *prefix, CodecId codec) {
|
||||
char path[256];
|
||||
Track::Ptr track;
|
||||
switch (codec) {
|
||||
case CodecAAC:
|
||||
track.reset(new AACTrack(44100, 1));
|
||||
sprintf(path, "%s_aac.mp4", prefix);
|
||||
break;
|
||||
case CodecOpus:
|
||||
track.reset(new OpusTrack());
|
||||
sprintf(path, "%s_opus.mp4", prefix);
|
||||
break;
|
||||
case CodecG711A:
|
||||
case CodecG711U:
|
||||
track.reset(new G711Track(codec, 8000, 1, 16));
|
||||
sprintf(path, "%s_711%c.mp4", prefix, codec == CodecG711A ? 'A' : 'U');
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
file.reset(new MP4Muxer());
|
||||
file->openMP4(path);
|
||||
file->addTrack(track);
|
||||
enc.reset(new FFmpegEncoder(track));
|
||||
enc->setOnEncode([this](const Frame::Ptr &frame) { file->inputFrame(frame); });
|
||||
}
|
||||
~TransCtx() {
|
||||
enc = nullptr;
|
||||
file = nullptr;
|
||||
}
|
||||
void inputFrame(const FFmpegFrame::Ptr &frame) { enc->inputFrame(frame, false); }
|
||||
FFmpegEncoder::Ptr enc;
|
||||
std::shared_ptr<MP4Muxer> file;
|
||||
};
|
||||
|
||||
int TranscodeAudio(const char *srcPath, const char *dstPath) {
|
||||
MP4Demuxer srcMp4;
|
||||
srcMp4.openMP4(srcPath);
|
||||
|
||||
auto srcTrack = srcMp4.getTrack(TrackAudio);
|
||||
if (!srcTrack) {
|
||||
printf("unable to find audioTrack %s\n", srcPath);
|
||||
return -1;
|
||||
}
|
||||
std::vector<TransCtx::Ptr> trans;
|
||||
FFmpegDecoder audioDec(srcTrack);
|
||||
auto dstCodec = getCodecId(dstPath);
|
||||
if (!strcasecmp(dstPath, "aac"))
|
||||
dstCodec = CodecAAC;
|
||||
if (dstCodec != CodecInvalid) {
|
||||
std::string dstFile(srcPath);
|
||||
auto pos = dstFile.rfind('_');
|
||||
if (pos == dstFile.npos)
|
||||
pos = dstFile.rfind('.');
|
||||
if (pos != dstFile.npos)
|
||||
dstFile = dstFile.substr(0, pos);
|
||||
if (dstCodec == srcTrack->getCodecId()) {
|
||||
printf("same codec %s, skip transcode\n", dstPath);
|
||||
return 0;
|
||||
}
|
||||
trans.push_back(std::make_shared<TransCtx>(dstFile.c_str(), dstCodec));
|
||||
}
|
||||
else {
|
||||
for (auto codec : { CodecAAC, CodecOpus, CodecG711A, CodecG711U }) {
|
||||
if (codec == srcTrack->getCodecId())
|
||||
continue;
|
||||
trans.push_back(std::make_shared<TransCtx>(dstPath, codec));
|
||||
}
|
||||
}
|
||||
// srcTrack -> audioDec
|
||||
srcTrack->addDelegate([&](const Frame::Ptr &frame) -> bool {
|
||||
audioDec.inputFrame(frame, true, false, false);
|
||||
return true;
|
||||
});
|
||||
// audioDec -> audioEnc
|
||||
audioDec.setOnDecode([&](const FFmpegFrame::Ptr &frame) {
|
||||
for (TransCtx::Ptr p : trans)
|
||||
p->inputFrame(frame);
|
||||
});
|
||||
toolkit::Ticker tick;
|
||||
printf("startReadMp4 %" PRIu64 "ms\n", srcMp4.getDurationMS());
|
||||
bool key, eof;
|
||||
Frame::Ptr frame;
|
||||
while (true) {
|
||||
// srcMp4->srcTrack
|
||||
frame = srcMp4.readFrame(key, eof);
|
||||
if (eof) {
|
||||
printf("eof break loop, it tooks %" PRIu64 " ms\n", tick.elapsedTime());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc != 3) {
|
||||
printf("usage src.mp4 dst_prefix/codecName\n");
|
||||
return 0;
|
||||
}
|
||||
toolkit::Logger::Instance().add(std::make_shared<toolkit::ConsoleChannel>());
|
||||
try {
|
||||
return TranscodeAudio(argv[1], argv[2]);
|
||||
} catch (std::exception e) {
|
||||
printf("exception: %s\n", e.what());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user