简体   繁体   中英

FFMPEG passthrough recording RTSP/H264 to MP4 container bad encoding

Hello I'm using the ffmpeg 3.4.2 to record a RTSP h264 steam from an IP camera. I have a working example however at the beginning I see some corrupted images, after a couple of seconds the video is shown properly. I was wondering if this is a timing issue.

在此处输入图片说明

The source code which illustrates opening and reading a RTSP stream, and writing it into an MP4 container.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <sys/time.h>

extern "C" {
  #include <libavcodec/avcodec.h>
  #include <libavutil/opt.h>
  #include <libavutil/imgutils.h>
  #include <libavformat/avformat.h>
  #include <libavformat/avio.h>
  #include <libswscale/swscale.h>
}

time_t get_time()
{
  struct timeval tv;

  gettimeofday( &tv, NULL );

  return tv.tv_sec;
}

int main(int argc, char **argv)
{
    const char *filename, *codec_name;
    const AVCodec *codec;
    AVCodecContext *c= NULL;
    int i, ret, x, y;


    // Open the initial context variables that are needed
    AVFormatContext* format_ctx = avformat_alloc_context();
    int video_stream_index;

    // Register everything
    av_register_all();
    avformat_network_init();

    //open RTSP

    AVDictionary *ifmtdict;
    av_dict_set(&ifmtdict, "rtsp_transport", "tcp", 0);

    if (avformat_open_input(&format_ctx, "rtsp://192.168.0.84/user=admin_password=_channel=1_stream=0.sdp",
            NULL, &ifmtdict) != 0) {
        return EXIT_FAILURE;
    }

    if (avformat_find_stream_info(format_ctx, NULL) < 0) {
        return EXIT_FAILURE;
    }

    //search video stream
    for (int i = 0; i < format_ctx->nb_streams; i++) {
        if (format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
            video_stream_index = i;
    }

    AVPacket packet;
    av_init_packet(&packet);

    AVStream* stream = NULL;
    int cnt = 0;

    //start reading packets from stream and write them to file
    av_read_play(format_ctx);    //play RTSP

    // Get the codec
    codec = avcodec_find_decoder(AV_CODEC_ID_H264);
    if (!codec) {
        exit(1);
    }

    // Prepare the output
    AVFormatContext* oc = avformat_alloc_context();
    oc->oformat = av_guess_format(NULL, "video.mp4", NULL);
    avio_open2(&oc->pb, "video.mp4", AVIO_FLAG_WRITE, NULL, NULL);

    // Write header
    stream = avformat_new_stream(oc, (AVCodec*) format_ctx->streams[video_stream_index]->codec->codec);
    avcodec_parameters_copy(stream->codecpar, format_ctx->streams[video_stream_index]->codecpar);
    stream->sample_aspect_ratio = format_ctx->streams[video_stream_index]->codec->sample_aspect_ratio;
    stream->codecpar->codec_tag  = 0;
    stream->time_base = format_ctx->streams[video_stream_index]->time_base;
    avformat_write_header(oc, NULL);

    time_t timenow, timestart;
    timestart = timenow = get_time();
    bool got_key_frame = 0;

    while (av_read_frame(format_ctx, &packet) >= 0 && cnt < 200000) { //read ~ 200000 frames
        if (packet.stream_index == video_stream_index) {    //packet is video
            // Make sure we start on a key frame
            if ( !got_key_frame && timestart == timenow && ! ( packet.flags & AV_PKT_FLAG_KEY ) ) {
              timestart = timenow = get_time();
              continue;
            }
            got_key_frame = 1;
            std::cout << cnt << std::endl;
            av_interleaved_write_frame( oc, &packet );
            cnt++;
        }
      av_free_packet(&packet);
      av_init_packet(&packet);
      timenow = get_time();
    }

    av_write_trailer(oc);
    avcodec_close(stream->codec);
    avio_close(oc->pb);
    avformat_free_context(oc);

    av_read_pause(format_ctx);

    avcodec_free_context(&c);
    avformat_network_deinit();

    return 0;
}

A H.264 stream consists of Group of Frames (GOP). Usually you can only start decoding at GOP boundaries. You may have to wait for an IDR frame before you passthrough video packets to the MP4 writer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM