提问人:Ehsan Vahab 提问时间:9/20/2023 最后编辑:Ehsan Vahab 更新时间:9/21/2023 访问量:40
C++ LibAV 将原始 H264 复用到 MP4 容器中并保留在缓冲区中
C++ LibAV muxing raw H264 into MP4 container and keeping on the buffer
问:
我有一组原始的 H264 AVPackets,它们来自 IP Camera 的 RTSP。
所以我要把它们放到 MP4 容器中(而不是文件放到缓冲区中),然后在网络上流式传输缓冲区。
我在 ffmpeg 网站上阅读了示例并在 Stackoverflow 上冲浪了很多,所以编写以下代码,但最后当我将 mp4 结果从 bufer 写入文件时,它无法播放。事件:我在循环中写入 buufer,它无法播放,并且缓冲区内似乎有空包。
但是,当我使用 libav 使用和写入文件时,它工作正常并且文件可以播放。avio_open2
#include <iostream>
#include <vector>
#include <queue>
#include "stdlib.h"
#include <fstream>
#include <list>
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/avutil.h>
#include <libavutil/pixdesc.h>
#include <libswscale/swscale.h>
#include "libavutil/imgutils.h"
#include <libavutil/opt.h>
#include <libavutil/mathematics.h>
}
#define VIDEO_CODEC_ID AV_CODEC_ID_H264
#define AUDIO_CODEC_ID AV_CODEC_ID_AAC
#define BUFFER_SIZE 1024*1024*10 // 10 MB buffer size (adjust as needed)
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/img_hash.hpp>
#include "opencv2/imgproc/imgproc.hpp"
#include <pthread.h>
#include <assert.h>
#include <algorithm>
#include <limits>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <bitset>
using namespace std;
using namespace cv;
int main(int argc, char ** argv) {
av_register_all();
avcodec_register_all();
FILE *fp;
fp = fopen("./sample_iocontext.mp4", "wb");
// Muxer2
AVFormatContext* muxer2 = avformat_alloc_context();
muxer2->oformat = av_guess_format("mp4", NULL, NULL);
AVStream* video_track2 = avformat_new_stream(muxer2, NULL);
//Muxer2
avcodec_parameters_from_context(video_track2->codecpar, mycodec); //sample codec from another function
video_track2->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
video_track2->codec->codec_id = AV_CODEC_ID_H264;
video_track2->codec->codec_type = AVMEDIA_TYPE_VIDEO;
video_track2->codec->width = 1280;
video_track2->codec->height = 960;
video_track2->codec->time_base.den = 20;
video_track2->codec->time_base.num = 1;
video_track2->time_base = (AVRational) {1,20};
video_track2->avg_frame_rate = mycodec->framerate;
muxer2->oformat->video_codec = AV_CODEC_ID_H264;
avio_buffer = (uint8_t*)av_malloc(BUFFER_SIZE);
AVIOContext* ioContext = avio_alloc_context(avio_buffer, BUFFER_SIZE, 1, nullptr, nullptr, nullptr, nullptr);
ioContext->seekable = 1;
muxer2->pb = ioContext;
muxer2->flags = AVFMT_FLAG_CUSTOM_IO;
// Write MP4 container header to memory buffer
AVDictionary *options = NULL;
av_dict_set(&options, "live", "1", 0);
avformat_write_header(muxer2, &options);
int packetId=0;
for(int ii=0;ii<100;ii++){
AVPacket *temp_packet2; //get packet from my array of AVPacket
AVRational encoder_time_base = (AVRational) {1, 20};
temp_packet2->stream_index = video_track2->index;
int64_t scaled_pts2 = av_rescale_q(packetId, encoder_time_base, video_track2->time_base);
temp_packet2->pts = scaled_pts2;
int64_t scaled_dts2 = av_rescale_q(packetId, encoder_time_base, video_track2->time_base);
temp_packet2->dts = scaled_dts2;
packetId++;
av_interleaved_write_frame(muxer2, temp_packet2);
av_packet_free(&temp_packet2);
}
// Write MP4 container trailer to memory buffer
av_write_trailer(muxer2);
fwrite(avio_buffer, 1, ioContext->pos, fp);
fclose(fp);
av_freep(&avio_buffer);
avformat_free_context(muxer2);
return 0;
}
答:
1赞
Ehsan Vahab
9/21/2023
#1
一周后,我发现这是 mp4 容器的正常行为。
实际上,MP4 非常适合 OR,而不是直播的可靠选择。Althogh 容器具有更高的压缩比和更少的使用,需要全部生成,所以等待调用,意味着没有视频帧和写入,要把。这就是为什么内存对于 .
我建议使用或通过网络发送实时流数据包。VOD
offline playback
mp4
B/W
mp4 muxer
AVPacket
meta information
LibAVFormat
av_write_trailer
meta tags
header/footer segment
seekable
mp4 muxer
HLS
DASH
评论