I have an array of raw H264 AVPackets which get from IP Camera's RTSP.
so I'm going to put them into MP4 container (not to the file into the buffer) then stream the buffer on the network.
I read example on ffmpeg site and surfe alot on Stackoverflow so write the following code but finally when I write the mp4 result from the bufer to the file, it's not playable. event I write the buufer inside the loop it can not be played and seems there's empty packet inside the buffer.
however when I use avio_open2 and write to the file with libav it works fine and the file is playable.
#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;
}
after one week I find that it's a normal behavior of mp4 container. actually mp4 is very fit for
VODoroffline playback, and not a sutible option for live streaming. Althoghmp4container has higher compression ratio and use lessB/W,mp4 muxerneeds allAVPacketto generatemeta information, soLibAVFormatwait to callav_write_trailer,means there's no video frame and writemeta tags, to putheader/footer segment. that's whyseekablememory is essential formp4 muxer. I suggest to useHLSorDASHto send live streaming packet over the network.