mirror of
https://github.com/SunnyQjm/ndn_ffmpeg_rtc.git
synced 2026-10-05 01:15:41 +08:00
105 lines
3.4 KiB
C++
105 lines
3.4 KiB
C++
//
|
|
// Created by mingj on 2019/10/16.
|
|
//
|
|
|
|
#include "FFmpegHelper.h"
|
|
|
|
void FFmpegHelper::init() {
|
|
av_register_all();
|
|
avformat_network_init();
|
|
avdevice_register_all();
|
|
}
|
|
|
|
FFmpegHelper::FFmpegHelper() {
|
|
|
|
}
|
|
|
|
FFmpegHelper::~FFmpegHelper() {
|
|
// 自动释放资源
|
|
if (pFormatContext) {
|
|
avformat_free_context(pFormatContext);
|
|
}
|
|
}
|
|
|
|
FFmpegHelper *FFmpegHelper::initFormatContext() {
|
|
pFormatContext = avformat_alloc_context();
|
|
return this;
|
|
}
|
|
|
|
FFmpegHelper *FFmpegHelper::openCamera(const std::string &av_input_short_name, const std::string &url) {
|
|
// Linux 打开摄像头设备的输入流
|
|
AVInputFormat *avInputFormat = av_find_input_format(av_input_short_name.c_str());
|
|
av_register_input_format(avInputFormat);
|
|
if (avformat_open_input(&pFormatContext, url.c_str(), avInputFormat, nullptr) != 0) {
|
|
throw FFmpegFailedException("Couldn't open input stream.");
|
|
}
|
|
|
|
if (avformat_find_stream_info(pFormatContext, nullptr) < 0) {
|
|
throw FFmpegFailedException("Couldn't find stream information.");
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
int FFmpegHelper::findFirstStreamIndexByType(enum AVMediaType avMediaType) {
|
|
for (unsigned int i = 0; i < this->pFormatContext->nb_streams; i++) {
|
|
if (pFormatContext->streams[i]->codecpar->codec_type == avMediaType) {
|
|
return static_cast<int>(i);
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
AVFormatContext *FFmpegHelper::getFormatContext() {
|
|
return pFormatContext;
|
|
}
|
|
|
|
AVCodecContext *FFmpegHelper::openCodec(enum AVMediaType avMediaType) {
|
|
int index = this->findFirstStreamIndexByType(avMediaType);
|
|
AVCodecContext *pCodecCtx = this->pFormatContext->streams[index]->codec;
|
|
AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
|
|
if (pCodec == nullptr) {
|
|
throw FFmpegFailedException("Codec not found.");
|
|
}
|
|
if (avcodec_open2(pCodecCtx, pCodec, nullptr) < 0) {
|
|
throw FFmpegFailedException("Could not open codec.");
|
|
}
|
|
return pCodecCtx;
|
|
}
|
|
|
|
AVFrame *FFmpegHelper::allocAVFrameAndDataBufferWithType(enum AVPixelFormat pix_fmt, int width, int height, int align) {
|
|
AVFrame *pFrame = av_frame_alloc();
|
|
u_char *outBuffer = nullptr;
|
|
outBuffer = (u_char *) av_malloc(av_image_get_buffer_size(pix_fmt, width, height, align));
|
|
av_image_fill_arrays(pFrame->data, pFrame->linesize, outBuffer, pix_fmt, width, height, align);
|
|
return pFrame;
|
|
}
|
|
|
|
AVPacket *FFmpegHelper::allocAVPacket() {
|
|
return (AVPacket *) av_malloc(sizeof(AVPacket));
|
|
}
|
|
|
|
SwsContext *FFmpegHelper::SWS_GetContext(AVCodecContext *pCodecContext, enum AVPixelFormat dstFormat, int flags,
|
|
SwsFilter *srcFilter, SwsFilter *dstFilter, const double *param) {
|
|
SwsContext *swsContext = nullptr;
|
|
swsContext = sws_getContext(pCodecContext->width, pCodecContext->height, pCodecContext->pix_fmt,
|
|
pCodecContext->width,
|
|
pCodecContext->height, dstFormat, flags, srcFilter, dstFilter, param);
|
|
return swsContext;
|
|
}
|
|
|
|
FFmpegHelper *FFmpegHelper::decode(AVCodecContext *avCodecContext, AVPacket *packet, AVFrame *pFrame,
|
|
const DecodeCallbackFunc& callbackFunc) {
|
|
int ret = avcodec_send_packet(avCodecContext, packet);
|
|
if (ret != 0)
|
|
return this;
|
|
while (avcodec_receive_frame(avCodecContext, pFrame) >= 0) {
|
|
callbackFunc(pFrame);
|
|
}
|
|
av_packet_unref(packet);
|
|
return this;
|
|
}
|
|
|
|
|
|
|