整体方案:
采集端:摄像头采集(YUV)->编码(YUV转H264)->RTMP推流客户端:RTMP拉流->解码(H264转YUV)->YUV显示(SDL2)
下面是采集摄像头的YUV数据相关代码。
主程序:
#include
#include
#ifdef __cplusplus
extern "C"
{
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#ifdef __cplusplus
}
#endif
#include "stdio.h"
#include "string.h"
//#include "ffmpeg_function.h"
void ffmpeg_video(void)
{
char errors[1024]={0};
//int file_fd=0;
//create file
FILE* file_fd=fopen("./video.yuv","wb");
//ctx
AVFormatContext *fmt_ctx=NULL;
AVDictionary *option =NULL;
//packet
int count =0;
AVPacket pkt;
char devicename[1024]="/dev/video0";
//注册设备
avdevice_register_all();
AVInputFormat *iformat=av_find_input_format("video4linux2");
av_dict_set(&option,"video_size","640x480",0);
av_dict_set(&option,"framerate","30",0); //指定帧率
av_dict_set(&option,"pixel_format","nv12",0); //指定格式
//打开设备
int ret=avformat_open_input(&fmt_ctx,devicename,iformat,&option);
if (ret<0)
{
av_strerror(ret,errors,1024);
return;
}
av_init_packet(&pkt);
while (ret=av_read_frame(fmt_ctx,&pkt)==0&&count++<30)
{
printf("packet size is %d(%p),count=%d\n",pkt.size,pkt.data,count);
fwrite((pkt.data), 1,pkt.size, file_fd);
}
av_packet_unref(&pkt);
fclose(file_fd);
avformat_close_input(&fmt_ctx);
av_log_set_level(AV_LOG_DEBUG);
av_log( NULL, AV_LOG_DEBUG,"hello,word\n");
}
int main(int argc, char **argv)
{
ffmpeg_video();
return 0;
}
Makefile:
PRJ_PATH = .
TARGETS = video_prj
DIR_INC = ./inc
DIR_SRC = ./src
DIR_OBJ = ./obj
CXX = g++
SRC := $(wildcard ${DIR_SRC}/*.cpp)
OBJ := $(patsubst ${DIR_SRC}/%.cpp,$(DIR_OBJ)/%.o,$(SRC))
FFMPEG_LIB_DIR = $(PRJ_PATH)/third_lib/ffmpeg/lib
FFMPEG_INC_DIR = $(PRJ_PATH)/third_lib/ffmpeg/include
INCLUDES = -I$(DIR_INC)
INCLUDES += -I$(FFMPEG_INC_DIR)
LDFLAGS = -ldl -lpthread -lm
LDFLAGS += -lX11 -lasound -lmp3lame -lz -lrt
LDFLAGS += -L$(FFMPEG_LIB_DIR) -lavformat -lavdevice -lavcodec -lavutil -lavfilter -lpostproc -lswresample -lswscale
CXXFLAGS = -fpermissive
CXXFLAGS += -fPIC
CFLAGS += $(INCLUDES)
$(TARGETS):$(OBJ)
$(CXX) $^ -o $@ $(LDFLAGS) $(CXXFLAGS)
$(DIR_OBJ)/%.o:$(DIR_SRC)/%.cpp
$(CXX) $(CFLAGS) -c $< -o $@ $(CXXFLAGS)
clean:
rm -f $(TARGETS)
rm -f $(DIR_OBJ)/*.o
工程结构(详细的工程目录,参考YUV转H264章节):
$ tree .
.
├── inc
├── Makefile
├── obj
│ ├── dev2yuv.o
│ └── yuv2h264.o
├── src
│ └── dev2yuv.cpp
├── third_lib
│ └── ffmpeg
│ ├── include
│ │ ├── libavcodec
│ │ │ ├── ac3_parser.h
│ │ │ ├── adts_parser.h
│ │ │ ├── avcodec.h
│ │ │ ├── avdct.h
│ │ │ ├── avfft.h
│ │ │ ├── d3d11va.h
│ │ │ ├── dirac.h
│ │ │ ├── dv_profile.h
│ │ │ ├── dxva2.h
│ │ │ ├── jni.h
│ │ │ ├── mediacodec.h
│ │ │ ├── qsv.h
│ │ │ ├── vaapi.h
│ │ │ ├── vdpau.h
│ │ │ ├── version.h
│ │ │ ├── videotoolbox.h
│ │ │ ├── vorbis_parser.h
│ │ │ └── xvmc.h
│ │ ├── libavdevice
│ │ │ ├── avdevice.h
│ │ │ └── version.h
│ │ ├── libavfilter
│ │ │ ├── avfilter.h
│ │ │ ├── buffersink.h
│ │ │ ├── buffersrc.h
│ │ │ └── version.h
│ │ ├── libavformat
│ │ │ ├── avformat.h
│ │ │ ├── avio.h
│ │ │ └── version.h
│ │ ├── libavutil
│ │ │ ├── adler32.h
│ │ │ ├── aes_ctr.h
│ │ │ ├── aes.h
│ │ │ ├── attributes.h
│ │ │ ├── audio_fifo.h
│ │ │ ├── avassert.h
│ │ │ ├── avconfig.h
│ │ │ ├── avstring.h
│ │ │ ├── avutil.h
│ │ │ ├── base64.h
│ │ │ ├── blowfish.h
│ │ │ ├── bprint.h
│ │ │ ├── bswap.h
│ │ │ ├── buffer.h
│ │ │ ├── camellia.h
│ │ │ ├── cast5.h
│ │ │ ├── channel_layout.h
│ │ │ ├── common.h
│ │ │ ├── cpu.h
│ │ │ ├── crc.h
│ │ │ ├── des.h
│ │ │ ├── dict.h
│ │ │ ├── display.h
│ │ │ ├── downmix_info.h
│ │ │ ├── encryption_info.h
│ │ │ ├── error.h
│ │ │ ├── eval.h
│ │ │ ├── ffversion.h
│ │ │ ├── fifo.h
│ │ │ ├── file.h
│ │ │ ├── frame.h
│ │ │ ├── hash.h
│ │ │ ├── hdr_dynamic_metadata.h
│ │ │ ├── hmac.h
│ │ │ ├── hwcontext_cuda.h
│ │ │ ├── hwcontext_d3d11va.h
│ │ │ ├── hwcontext_drm.h
│ │ │ ├── hwcontext_dxva2.h
│ │ │ ├── hwcontext.h
│ │ │ ├── hwcontext_mediacodec.h
│ │ │ ├── hwcontext_qsv.h
│ │ │ ├── hwcontext_vaapi.h
│ │ │ ├── hwcontext_vdpau.h
│ │ │ ├── hwcontext_videotoolbox.h
│ │ │ ├── imgutils.h
│ │ │ ├── intfloat.h
│ │ │ ├── intreadwrite.h
│ │ │ ├── lfg.h
│ │ │ ├── log.h
│ │ │ ├── lzo.h
│ │ │ ├── macros.h
│ │ │ ├── mastering_display_metadata.h
│ │ │ ├── mathematics.h
│ │ │ ├── md5.h
│ │ │ ├── mem.h
│ │ │ ├── motion_vector.h
│ │ │ ├── murmur3.h
│ │ │ ├── opt.h
│ │ │ ├── parseutils.h
│ │ │ ├── pixdesc.h
│ │ │ ├── pixelutils.h
│ │ │ ├── pixfmt.h
│ │ │ ├── random_seed.h
│ │ │ ├── rational.h
│ │ │ ├── rc4.h
│ │ │ ├── replaygain.h
│ │ │ ├── ripemd.h
│ │ │ ├── samplefmt.h
│ │ │ ├── sha512.h
│ │ │ ├── sha.h
│ │ │ ├── spherical.h
│ │ │ ├── stereo3d.h
│ │ │ ├── tea.h
│ │ │ ├── threadmessage.h
│ │ │ ├── timecode.h
│ │ │ ├── time.h
│ │ │ ├── timestamp.h
│ │ │ ├── tree.h
│ │ │ ├── twofish.h
│ │ │ ├── tx.h
│ │ │ ├── version.h
│ │ │ └── xtea.h
│ │ ├── libpostproc
│ │ │ ├── postprocess.h
│ │ │ └── version.h
│ │ ├── libswresample
│ │ │ ├── swresample.h
│ │ │ └── version.h
│ │ └── libswscale
│ │ ├── swscale.h
│ │ └── version.h
│ └── lib
│ ├── libavcodec.so
│ ├── libavdevice.so
│ ├── libavfilter.so
│ ├── libavformat.so
│ ├── libavutil.so
│ ├── libpostproc.so
│ ├── libswresample.so
│ └── libswscale.so
└── video_prj