开始之初想搞一搞鸿蒙的底层,后来经过实践发现,差点把自己搞泪崩,于是只能换个方向测评了。
早上上班路过公司楼下的时候,发现之前架的摄像头还在,于是到位置上的第一件事情就确认一下这个摄像头是否还能用,于是这篇测评文章诞生了。
首先把系统刷成Ubuntu的版本的,配置各种环境(IP SSH samba 交叉工具链等),在一通操作完成之后,就吧啦吧啦搞代码,ffmpeg库交叉编译。
一、直接用ffplay指令拉流,先看看效果,效果肯定出的来对吧,不太好的是很耗资源,图片有标记
拉出来的视频中间有一小会不太流畅,看视频内容。一路视频不太应该出现这样现象,回头再查查原因。
二、通过程序去拉流保存成视频格式,进行播放,过程如下图
附上相关的代码(电脑的代码出于安全考虑拷贝不出来,找了个差不多的代码粘贴上来)如下:
#include#include#include#define__STDC_CONSTANT_MACROS#ifdef__cplusplusextern"C"{#endif#include#include#include"libavutil/mathematics.h"#include"libavutil/time.h"#include#ifdef__cplusplus}#endifstaticdoubler2d(AVRationalr){returnr.num ==0|| r.den ==0?0.: (double)r.num / (double)r.den; }intmain(intargc,char**argv) {AVOutputFormat*ofmt =NULL;AVFormatContext*ifmt_ctx =NULL, *ofmt_ctx =NULL;AVPacketpkt;charin_filename[128] = {0}, out_filename[128] = {0};intret, i;intstream_index =0;intvideo_index=-1;intframe_index=0;intI_received =0;intframes_count =-1;boolpush_stream =false,firstframe_flag=true;char*ofmt_name =NULL;AVRationalframe_rate;doubleduration;AVDictionary* opts =NULL;longlongstartTime; frames_count=100;longlongpulltime=100*1000000;strcpy(in_filename,"rtsp://guest:Guest123@172.1.64.153:554/h264/ch1/main/av_stream"); strcpy(out_filename,"2_tt.flv"); av_register_all(); avformat_network_init();AVDictionary*avdic=NULL;charoption_key[]="rtsp_transport";charoption_value[]="tcp"; av_dict_set(&avdic,option_key,option_value,0);charoption_key2[]="max_delay";charoption_value2[]="5000000"; av_dict_set(&avdic,option_key2,option_value2,0); ifmt_ctx = avformat_alloc_context();if((ret = avformat_open_input(&ifmt_ctx, in_filename,0, &avdic)) <0) { printf("Could not open input file '%s'", in_filename);gotoend; }if((ret = avformat_find_stream_info(ifmt_ctx,0)) <0) { printf("Failed to retrieve input stream information");gotoend; }for(i=0;inb_streams;i++) {if(ifmt_ctx->streams[i]->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {video_index=i;break; } } av_dump_format(ifmt_ctx,0, in_filename,0);if(strstr(out_filename,"rtmp://") !=NULL) { push_stream =true; ofmt_name =(char*)"flv"; }elseif(strstr(out_filename,"rtsp://") !=NULL) { push_stream =true; ofmt_name =(char*)"rtsp"; }elseif(strstr(out_filename,"udp://") !=NULL) { push_stream =true; ofmt_name = (char*)"mpegts"; }else{ push_stream =false; ofmt_name =NULL; } avformat_alloc_output_context2(&ofmt_ctx,NULL, ofmt_name, out_filename);if(!ofmt_ctx) { printf("Could not create output context\n"); ret =AVERROR_UNKNOWN;gotoend; } ofmt = ofmt_ctx->oformat;#if1for(i =0; i < ifmt_ctx->nb_streams; i++) {AVStream*in_stream = ifmt_ctx->streams[i];AVCodecParameters*in_codecpar = in_stream->codecpar;if(in_codecpar->codec_type !=AVMEDIA_TYPE_AUDIO&& in_codecpar->codec_type !=AVMEDIA_TYPE_VIDEO&& in_codecpar->codec_type !=AVMEDIA_TYPE_SUBTITLE) {continue; }if(push_stream && (in_codecpar->codec_type ==AVMEDIA_TYPE_VIDEO)) { frame_rate = av_guess_frame_rate(ifmt_ctx, in_stream,NULL); duration = (frame_rate.num && frame_rate.den ? av_q2d((AVRational){frame_rate.den, frame_rate.num}) :0); }AVCodec*codec = avcodec_find_decoder(in_stream->codecpar->codec_id);AVStream*out_stream = avformat_new_stream(ofmt_ctx,codec);if(!out_stream) { printf("Failed allocating output stream\n"); ret =AVERROR_UNKNOWN;gotoend; } ret = avcodec_parameters_copy(out_stream->codecpar, in_codecpar);if(ret <0) { printf("Failed to copy codec parameters\n");gotoend; } out_stream->codecpar->codec_tag =0;if(ofmt_ctx->oformat->flags &AVFMT_GLOBALHEADER){AVCodecContext*pCodecCtx_out = avcodec_alloc_context3(NULL); avcodec_parameters_to_context(pCodecCtx_out,out_stream->codecpar);pCodecCtx_out->flags |=AV_CODEC_FLAG_GLOBAL_HEADER; } }av_dump_format(ofmt_ctx,0, out_filename,1);if(!(ofmt->flags &AVFMT_NOFILE)) {ret = avio_open(&ofmt_ctx->pb, out_filename,AVIO_FLAG_WRITE);if(ret <0) { printf("Could not open output file '%s'", out_filename);gotoend; } }av_dict_set(&opts,"flvflags","no_duration_filesize",0); ret = avformat_write_header(ofmt_ctx, opts ? &opts :NULL);if(ret <0) { printf("Error occurred when opening output file\n");gotoend; } startTime = av_gettime();while(1) {AVStream*in_stream, *out_stream;ret = av_read_frame(ifmt_ctx, &pkt);if(ret <0) {break; } in_stream = ifmt_ctx->streams[pkt.stream_index]; out_stream = ofmt_ctx->streams[pkt.stream_index];if(pkt.stream_index==video_index) {if((pkt.flags &AV_PKT_FLAG_KEY) && (I_received ==0)) I_received =1;if(I_received ==0)continue; printf("Receive %8d video frames from input URL\n",frame_index); frame_index++; }else{continue; }if(!push_stream){longlongpasttime = av_gettime() - startTime;if(pasttime>pulltime)break; }if(firstframe_flag){ firstframe_flag=false; pkt.pts =0; pkt.dts =0; }else{ pkt.pts = av_rescale_q_rnd(pkt.pts,in_stream->time_base,out_stream->time_base,(enumAVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX)); pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, (enumAVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX)); }pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base); pkt.pos =-1;intcodec_type = in_stream->codecpar->codec_type;if(push_stream && (codec_type ==AVMEDIA_TYPE_VIDEO)) {AVRationaltb = in_stream->time_base;longlongnow = av_gettime() - startTime;longlongdts =0; dts = pkt.dts * (1000*1000* r2d(tb));if(dts > now){ av_usleep(dts - now); }}ret = av_interleaved_write_frame(ofmt_ctx, &pkt);if(ret <0) {if(ret==-22){continue; }else{ printf("Error muxing packet.error code %d\n", ret);break; } } av_packet_unref(&pkt); }av_write_trailer(ofmt_ctx);#endifend: av_dict_free(&avdic); avformat_close_input(&ifmt_ctx);if(ofmt_ctx && !(ofmt->flags &AVFMT_NOFILE)) { avio_closep(&ofmt_ctx->pb); } avformat_free_context(ofmt_ctx);if(ret <0&& ret !=AVERROR_EOF) { printf("Error occurred: %d\n", ret);return1; }return0; }