I am quite confused about how to save a video stream into a mp4 file. I am using ffmpeg. Let me explain the problem:
- I connect to a network camera via RTSP (H.264 stream) with avformat_open_input(), avformat_find_stream_info(), av_read_play(), and I get frames with av_read_frame().
- Each time I get a frame with av_read_frame(), I store the corresponding AVPacket in a circular buffer.
- In some points in my application, a range of this circular buffer is selected. I find a key frame used to start from.
- Once I have a list of AVPacket's starting from a key frame, I write header, frames, and tail, as I described below in the code.
The problem is that the resulting mp4 video has artifacts if I try to watch it using VLC, Windows Media Player, or another one.
I have also realized that the pts of that packets are not continuous, while dts are continuous. I know about B frames, but is this a problem in my case?
// Prepare the output
AVFormatContext* oc = avformat_alloc_context();
oc->oformat = av_guess_format(NULL, "video.mp4", NULL);
// Must write header, packets, and trailing
avio_open2(&oc->pb, "video.mp4", AVIO_FLAG_WRITE, NULL, NULL);
// Write header
AVStream* stream = avformat_new_stream(oc, (AVCodec*) context->streams[video_stream_index]->codec->codec);
avcodec_copy_context(stream->codec, context->streams[video_stream_index]->codec);
stream->sample_aspect_ratio = context->streams[video_stream_index]->codec->sample_aspect_ratio;
avformat_write_header(oc, NULL);
// FOR EACH FRAME...
... av_write_frame(oc, circular[k]); ...
// Write trailer and close the file
av_write_trailer(oc);
avcodec_close(stream->codec);
avio_close(oc->pb);
avformat_free_context(oc);
Thank you so much,
First: when you work with the camera, it is better to work through an RTP over TCP (TCP as transport protocol). To enable this feature:
Second: After the packets start coming, wait for the first keyframe and start to write to the file from this moment.