Mux mp4 without video codec.

This commit is contained in:
Fancy code 2024-07-06 18:32:10 +08:00
parent 03993fde2e
commit 479248eb01
3 changed files with 20 additions and 152 deletions

View File

@ -69,17 +69,17 @@ void FfmpegMuxStreamV2::GetStreamData(const void *data, const size_t &size, cons
bool fileMuxing = false;
fileMuxing = mVideoStream->CheckStreamHeader(data, size);
if (fileMuxing) {
av_dump_format(mOutputFormat, 0, "./test.mp4", 1);
/* open the output file, if needed */
if (!(mOutputFormat->oformat->flags & AVFMT_NOFILE)) {
ret = avio_open(&mOutputFormat->pb, "./test.mp4", AVIO_FLAG_WRITE);
if (ret < 0) {
char error_str[AV_ERROR_MAX_STRING_SIZE] = {0};
LogError("Could not open '%s': %s\n",
"./test.mp4",
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret));
}
}
// av_dump_format(mOutputFormat, 0, "./test.mp4", 1);
// /* open the output file, if needed */
// if (!(mOutputFormat->oformat->flags & AVFMT_NOFILE)) {
// ret = avio_open(&mOutputFormat->pb, "./test.mp4", AVIO_FLAG_WRITE);
// if (ret < 0) {
// char error_str[AV_ERROR_MAX_STRING_SIZE] = {0};
// LogError("Could not open '%s': %s\n",
// "./test.mp4",
// av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret));
// }
// }
/* Write the stream header, if any. */
ret = avformat_write_header(mOutputFormat, nullptr);
if (ret < 0) {
@ -126,7 +126,6 @@ StatusCode inline FfmpegMuxStreamV2::OpenMuxOutputFile(const std::string &fileNa
mAudioStream->SetWriteSourceDataCallback(
std::bind(&FfmpegMuxStreamV2::GetAVPacketDataCallback, this, std::placeholders::_1));
}
return CreateStatusCode(STATUS_CODE_OK);
av_dump_format(mOutputFormat, 0, fileName.c_str(), 1);
/* open the output file, if needed */
if (!(mOutputFormat->oformat->flags & AVFMT_NOFILE)) {
@ -138,6 +137,7 @@ StatusCode inline FfmpegMuxStreamV2::OpenMuxOutputFile(const std::string &fileNa
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret));
}
}
return CreateStatusCode(STATUS_CODE_OK);
/* Write the stream header, if any. */
ret = avformat_write_header(mOutputFormat, &opt);
if (ret < 0) {

View File

@ -1,137 +0,0 @@
/*
* Copyright (c) 2023 Fancy Code.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "FfmpegMuxStreamV2.h"
#include "FfmpegOutputStream.h"
#include "ILog.h"
#include "MediaBase.h"
#include "StatusCode.h"
#ifdef __cplusplus
extern "C" {
#endif
#include <libavcodec/codec_id.h>
#include <libavcodec/packet.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libavutil/dict.h>
#include <libavutil/error.h>
#ifdef __cplusplus
}
#endif
#include <cstddef>
#include <functional>
#include <memory>
// #include <mutex>
#include <string>
FfmpegMuxStreamV2::FfmpegMuxStreamV2() : mOutputFormat(nullptr), mOptions(nullptr)
{
}
StatusCode FfmpegMuxStreamV2::OpenOutputFile(const std::string &fileName)
{
return OpenMuxOutputFile(fileName);
}
StatusCode FfmpegMuxStreamV2::CloseOutputFile(void)
{
if (mOutputFormat && mOutputFormat->pb) {
av_write_trailer(mOutputFormat);
}
if (mVideoStream) {
mVideoStream->UnInit();
}
if (mAudioStream) {
mAudioStream->UnInit();
}
if (nullptr == mOutputFormat) {
return CreateStatusCode(STATUS_CODE_OK);
}
if (!(mOutputFormat->oformat->flags & AVFMT_NOFILE)) {
/* Close the output file. */
avio_closep(&mOutputFormat->pb);
}
avformat_free_context(mOutputFormat);
return CreateStatusCode(STATUS_CODE_OK);
}
void FfmpegMuxStreamV2::GetStreamData(const void *data, const size_t &size, const StreamInfo &streamInfo)
{
if (streamInfo.mType == STREAM_TYPE_VIDEO_H264 && mVideoStream) {
mVideoStream->WriteSourceData(data, size);
}
if (streamInfo.mType == STREAM_TYPE_AUDIO_G711A && mAudioStream) {
mAudioStream->WriteSourceData(data, size);
}
}
StatusCode inline FfmpegMuxStreamV2::OpenMuxOutputFile(const std::string &fileName)
{
AVDictionary *opt = nullptr;
int ret = 0;
/* allocate the output media context */
avformat_alloc_output_context2(&mOutputFormat, nullptr, "mp4", fileName.c_str());
if (!mOutputFormat) {
LogError("Could not deduce output format from file.\n");
return CreateStatusCode(STATUS_CODE_NOT_OK);
}
/* Add the audio and video streams using the default format codecs
* and initialize the codecs. */
if (mOutputFormat->oformat->video_codec != AV_CODEC_ID_NONE) {
mVideoStream = AddStream(mOutputFormat, mOutputFormat->oformat->video_codec, AV_CODEC_ID_H264);
mVideoStream->SetWriteSourceDataCallback(
std::bind(&FfmpegMuxStreamV2::GetAVPacketDataCallback, this, std::placeholders::_1));
}
if (mOutputFormat->oformat->audio_codec != AV_CODEC_ID_NONE) {
mAudioStream = AddStream(mOutputFormat, mOutputFormat->oformat->audio_codec, AV_CODEC_ID_PCM_ALAW);
mAudioStream->SetWriteSourceDataCallback(
std::bind(&FfmpegMuxStreamV2::GetAVPacketDataCallback, this, std::placeholders::_1));
}
av_dump_format(mOutputFormat, 0, fileName.c_str(), 1);
/* open the output file, if needed */
if (!(mOutputFormat->oformat->flags & AVFMT_NOFILE)) {
ret = avio_open(&mOutputFormat->pb, fileName.c_str(), AVIO_FLAG_WRITE);
if (ret < 0) {
char error_str[AV_ERROR_MAX_STRING_SIZE] = {0};
LogError("Could not open '%s': %s\n",
fileName.c_str(),
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret));
}
}
/* Write the stream header, if any. */
ret = avformat_write_header(mOutputFormat, &opt);
if (ret < 0) {
char error_str[AV_ERROR_MAX_STRING_SIZE] = {0};
LogError("Error occurred when opening output file: %s\n",
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret));
return CreateStatusCode(STATUS_CODE_NOT_OK);
}
return CreateStatusCode(STATUS_CODE_OK);
}
void FfmpegMuxStreamV2::GetAVPacketDataCallback(AVPacket *pkt)
{
// std::lock_guard<std::mutex> locker(mMutex);
int ret = 0;
ret = av_interleaved_write_frame(mOutputFormat, pkt);
/* pkt is now blank (av_interleaved_write_frame() takes ownership of
* its contents and resets pkt), so that no unreferencing is necessary.
* This would be different if one used av_write_frame(). */
if (ret < 0) {
char error_str[AV_ERROR_MAX_STRING_SIZE] = {0};
LogInfo("Error while writing output packet: %s\n",
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret));
}
}
std::shared_ptr<FfmpegOutputStream> FfmpegMuxStreamV2::AddStream(AVFormatContext *outputFormat,
enum AVCodecID encodecId, enum AVCodecID decodecId)
{
auto stream = std::make_shared<FfmpegOutputStream>(encodecId, decodecId);
stream->Init(outputFormat);
return stream;
}

View File

@ -100,20 +100,25 @@ void FfmpegOutputStream::WriteSourceData(const void *data, const size_t &size)
mDecoder->DecodeData(data, size, mDecodeCallback);
return;
}
AVPacket *mTmpPkt = av_packet_alloc();
static unsigned long long u64Interval = 0;
AVRational in_timebase = (AVRational){1, 15};
if (mEncodeCallback) {
mTmpPkt->data = (uint8_t *)data;
mTmpPkt->size = size;
mTmpPkt->stream_index = mStream->index;
mTmpPkt->pts = u64Interval * 1000; // ת<><D7AA><EFBFBD><EFBFBD> us
mTmpPkt->duration = 0;
// mTmpPkt->pts = u64Interval * 1000; // ת<><D7AA><EFBFBD><EFBFBD> us
mTmpPkt->pts = av_rescale_q(u64Interval, (AVRational){1, 15}, mStream->time_base);
u64Interval++;
mTmpPkt->dts = mTmpPkt->pts;
u64Interval += 70;
/* copy packet */
av_packet_rescale_ts(mTmpPkt, in_timebase, mStream->time_base);
// av_packet_rescale_ts(mTmpPkt, in_timebase, mStream->time_base);
mTmpPkt->pos = -1;
mEncodeCallback(mTmpPkt);
}
av_packet_unref(mTmpPkt);
av_packet_free(&mTmpPkt);
}
void FfmpegOutputStream::SetWriteSourceDataCallback(std::function<void(AVPacket *pkt)> callback)
{