Skip to content

Instantly share code, notes, and snippets.

@heyanlong
Created November 29, 2019 09:25
Show Gist options
  • Save heyanlong/331e4bc789b84f25e50126ff12d66f0b to your computer and use it in GitHub Desktop.
Save heyanlong/331e4bc789b84f25e50126ff12d66f0b to your computer and use it in GitHub Desktop.
rtsp codec
cmake_minimum_required(VERSION 3.14)
PROJECT(m)
SET(CMAKE_CXX_STANDARD 11)
FIND_PATH(AVCODEC_INCLUDE_DIR libavcodec/avcodec.h)
FIND_LIBRARY(AVCODEC_LIBRARY avcodec)
FIND_PATH(AVFORMAT_INCLUDE_DIR libavformat/avformat.h)
FIND_LIBRARY(AVFORMAT_LIBRARY avformat)
AUX_SOURCE_DIRECTORY(src DIR_SRCS)
AUX_SOURCE_DIRECTORY(src/video DIR_SRCS)
SET(M_SRCS
${DIR_SRCS})
ADD_EXECUTABLE(${PROJECT_NAME} ${M_SRCS})
TARGET_INCLUDE_DIRECTORIES(${PROJECT_NAME} PRIVATE ${AVCODEC_INCLUDE_DIR} ${AVFORMAT_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${AVCODEC_LIBRARY} ${AVFORMAT_LIBRARY})
//
// Created by Yanlong He on 2019/11/29.
//
#include "codec.h"
namespace m {
namespace detect {
Codec::Codec(std::string url)
: _url(std::move(url)) {
setOptions();
}
void Codec::open() {
AVFormatContext *fmtCtx = avformat_alloc_context();
avformat_open_input(&fmtCtx, _url.c_str(), nullptr, &_opt);
_fmtCtx.reset(fmtCtx);
avformat_find_stream_info(fmtCtx, nullptr);
int ret, streamIndex;
AVCodec *codec = nullptr;
AVStream *st;
ret = av_find_best_stream(fmtCtx, AVMEDIA_TYPE_VIDEO, -1, -1, &codec, 0);
if (ret < 0) {
return;
}
streamIndex = ret;
st = fmtCtx->streams[streamIndex];
codec = avcodec_find_decoder(st->codecpar->codec_id);
_codecContext = avcodec_alloc_context3(codec);
avcodec_parameters_to_context(_codecContext, st->codecpar);
AVDictionary *opt = nullptr;
av_dict_set(&opt, "threads", "1", 0);
avcodec_open2(_codecContext, codec, &opt);
av_dict_free(&opt);
av_init_packet(&_packet);
_frame.reset(av_frame_alloc());
av_seek_frame(fmtCtx, streamIndex, 0, AVSEEK_FLAG_BACKWARD);
avformat_flush(fmtCtx);
}
AVFrame *Codec::frame() {
AVFrame *f = nullptr;
if (av_read_frame(_fmtCtx.get(), &_packet) == 0) {
if (_packet.stream_index == _streamIndex) {
int response = avcodec_send_packet(_codecContext, &_packet);
if (response >= 0) {
response = avcodec_receive_frame(_codecContext, _frame.get());
std::cout << response << std::endl;
if (response == AVERROR(EAGAIN) || response == AVERROR_EOF) {
std::cout << "receive err: " << response << std::endl;
} else if (response < 0) {
} else if (response >= 0) {
f = _frame.get();
}
} else {
std::cout << "send packet err: " << response << std::endl;
}
}
} else {
std::cout << "read frame err" << std::endl;
}
return f;
}
void Codec::setOptions() {
av_dict_set(&_opt, "allowed_media_types", "video", 0);
av_dict_set(&_opt, "reconnect_streamed", "1", 0);
av_dict_set(&_opt, "nobuffer", "1", 0);
av_dict_set(&_opt, "analyzeduration", "0", 0);
av_dict_set(&_opt, "rtsp_transport", "tcp", 0);
av_dict_set(&_opt, "buffer_size", "2097152", 0);
av_dict_set(&_opt, "max_delay", "0", 0);
av_dict_set(&_opt, "stimeout", "30000000", 0);
}
}
}
//
// Created by Yanlong He on 2019/11/29.
//
#ifndef M_CODEC_H
#define M_CODEC_H
#include <iostream>
#include <utility>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/dict.h>
};
namespace m {
namespace detect {
class Codec {
private:
std::string _url;
AVDictionary *_opt = nullptr;
std::unique_ptr<AVFormatContext> _fmtCtx;
std::unique_ptr<AVFrame> _frame;
AVPacket _packet;
AVCodecContext *_codecContext = nullptr;
int _streamIndex;
void setOptions();
public:
explicit Codec(std::string url);
void open();
AVFrame* frame();
};
}
}
#endif //M_CODEC_H
//
// Created by Yanlong He on 2019/11/29.
//
#include <iostream>
#include "video/codec.h"
int main(int argc, char **argv) {
m::detect::Codec codec("rtsp://127.0.0.1/live");
codec.open();
while (1) {
AVFrame *frame = codec.frame();
if (frame != nullptr) {
std::cout << frame->width << " x " << frame->height << std::endl;
}
}
return 0;
}
@shyboylpf
Copy link

copy

@yankooo
Copy link

yankooo commented Nov 29, 2019

偶像!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment