Сохранение кадров с сетевой камеры (RTSP) в файл mp4

Я совершенно не понимаю, как сохранить видеопоток в файл mp4. Я использую ффмпег. Позвольте мне объяснить проблему:

  1. Я подключаюсь к сетевой камере через RTSP (поток H.264) с помощью avformat_open_input(), avformat_find_stream_info(), av_read_play() и получаю кадры с помощью av_read_frame().
  2. Каждый раз, когда я получаю кадр с помощью av_read_frame(), я сохраняю соответствующий AVPacket в кольцевом буфере.
  3. В некоторых точках моего приложения выбран диапазон этого кольцевого буфера. Я нахожу ключевой кадр, с которого начинается.
  4. Когда у меня есть список AVPacket, начиная с ключевого кадра, я пишу заголовок, кадры и хвост, как описано ниже в коде.

Проблема в том, что полученное видео в формате mp4 имеет артефакты, если я пытаюсь посмотреть его с помощью VLC, Windows Media Player или другого.

Я также понял, что pts этих пакетов не непрерывны, а dts непрерывны. Я знаю про B-кадры, но в моем случае это проблема?

// 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);

Большое спасибо,


person Didac Perez Parera    schedule 11.12.2013    source источник
comment
Вы можете посмотреть rtmpdump для справки (или даже просто использовать librtmp напрямую) - rtmpdump.mplayerhq.hu   -  person benjymous    schedule 11.12.2013


Ответы (1)


Первое: при работе с камерой лучше работать через RTP через TCP (TCP как транспортный протокол). Чтобы включить эту функцию:

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

Второй: После того, как пакеты начнут приходить, дождитесь первого ключевого кадра и с этого момента начните запись в файл.

person Eugene    schedule 18.01.2014
comment
также я пишу много видеопотоков со многих IP-камер. все хорошо :) Извините за мой английский. - person Eugene; 18.01.2014