原文出自 http://blog.csdn.net/zxwangyun/article/details/8190638#reply ?? 作者? Sloan
?
這里在錄制時(shí),并沒有進(jìn)行轉(zhuǎn)碼,只是相當(dāng)于把rtsp視頻直接保存到一個(gè)文件中。
- #include?<stdio.h> ??
- ??
- #ifdef?__cplusplus ??
- extern ? "C" ?{??
- #endif ??
- #include?<libavcodec/avcodec.h> ??
- #include?<libavformat/avformat.h> ??
- //#include?<libswscale/swscale.h> ??
- ??
- #ifdef?_MSC_VER ??
- int ?strcasecmp( const ? char ?*s1,? const ? char ?*s2)??
- {??
- ???? while ?((*s1?!=? '\0' )??
- ????????&&?(tolower(*(unsigned? char ?*)?s1)?==??
- ????????tolower(*(unsigned? char ?*)?s2)))???
- ????{??
- ????????s1++;??
- ????????s2++;??
- ????}??
- ??
- ???? return ?tolower(*(unsigned? char ?*)?s1)?-?tolower(*(unsigned? char ?*)?s2);??
- }??
- int ?strncasecmp( const ? char ?*s1,? const ? char ?*s2,?unsigned? int ?n)??
- {??
- ???? if ?(n?==?0)??
- ???????? return ?0;??
- ??
- ???? while ?((n--?!=?0)??
- ????????&&?(tolower(*(unsigned? char ?*)?s1)?==??
- ????????tolower(*(unsigned? char ?*)?s2)))?{??
- ???????????? if ?(n?==?0?||?*s1?==? '\0' ?||?*s2?==? '\0' )??
- ???????????????? return ?0;??
- ????????????s1++;??
- ????????????s2++;??
- ????}??
- ??
- ???? return ?tolower(*(unsigned? char ?*)?s1)?-?tolower(*(unsigned? char ?*)?s2);??
- }??
- #endif?//_MSC_VER ??
- ??
- #ifdef?__cplusplus ??
- }??
- #endif ??
- ??
- /*********************************************************** ?
- '**?stream_component_open ?
- *???Description:? ?
- *????????????//open?the?stream?component?for?video/audio ?
- * ?
- * ?
- *???Params:ic-pointer?which?contains?the?url?and?codec?details? ?
- :stream_index-index?denoting?video?or?audio?stream ?
- ***********************************************************/ ??
- int ?stream_component_open(AVFormatContext?*ic,? int ?stream_index)??
- {??
- ????AVCodecContext?*enc;??
- ????AVCodec?*codec;??
- ??
- ???? if ?(stream_index?<?0?||?stream_index?>=?( int )ic->nb_streams)??
- ???????? return ?-1;??
- ????enc?=?ic->streams[stream_index]->codec;??
- ??
- ???? /*?prepare?audio?output?*/ ??
- ???? if ?(enc->codec_type?==?CODEC_TYPE_AUDIO)??
- ????{??
- ???????? if ?(enc->channels?>?0)??
- ????????????enc->request_channels?=?FFMIN(2,?enc->channels);??
- ???????? else ??
- ????????????enc->request_channels?=?2;??
- ??
- ???????? /*Hardcoding?the?codec?id?to?PCM_MULAW?if?the?audio ?
- ????????codec?id?returned?by?the?lib?is?CODEC_ID_NONE?*/ ??
- ??
- ???????? if (enc->codec_id?==?CODEC_ID_NONE)??
- ????????{??
- ????????????enc->codec_id?=?CODEC_ID_PCM_MULAW;??
- ????????????enc->channels?=?1;??
- ????????????enc->sample_rate?=?16000;??
- ????????????enc->bit_rate?=?128;??
- ????????}??
- ????}??
- ??
- ????codec?=?avcodec_find_decoder(enc->codec_id);??
- ????enc->idct_algo???????????=?FF_IDCT_AUTO;??
- ????enc->flags2???|=?CODEC_FLAG2_FAST;??
- ????enc->skip_frame??????????=?AVDISCARD_DEFAULT;??
- ????enc->skip_idct???????????=?AVDISCARD_DEFAULT;??
- ????enc->skip_loop_filter????=?AVDISCARD_DEFAULT;??
- ????enc->error_concealment???=?3;??
- ??
- ???? if ?(!codec?||?avcodec_open(enc,?codec)?<?0)??
- ???????? return ?-1;??
- ????avcodec_thread_init(enc,?1);??
- ????enc->thread_count=?1;??
- ????ic->streams[stream_index]->discard?=?AVDISCARD_DEFAULT;??
- ??
- ???? return ?0;??
- }??
- //聲明函數(shù) ??
- int ?enable_local_record(AVFormatContext?*ic /*已經(jīng)打開的視頻文件上下文*/ ,??
- ???????????????????????? int ?videostream, int ?audiostream,??
- ????????????????????????AVFormatContext?**out_oc, const ? char ?*?ofile, const ? char ?*?ofileformat);??
- ??
- int ?exit_onerr( const ? char ?*?err_desc /*錯(cuò)誤描述*/ , int ?err_code /*錯(cuò)誤碼*/ )??
- {??
- ????printf( "%s\n" ,err_desc);??
- ????system( "pause" ); //暫停,查看錯(cuò)誤描述 ??
- ???? return ?err_code;??
- }??
- int ?main( int ?argc,? char *?argv[])??
- {??
- ???? //初始化ffmpeg鏈表結(jié)構(gòu) ??
- ????avcodec_register_all();????????????????????? //?Register?all?formats?and?codecs ??
- ????av_register_all();??
- ??
- ????AVPacket??packet;??
- ??
- ???? //打開文件 ??
- ????AVFormatContext?*?ic?=?NULL;??
- ???? const ? char ?*?rtsp_url?=? "rtsp://192.168.0.168:8557/PSIA/Streaming/channels/2?videoCodecType=H.264" ;??
- ???? if (av_open_input_file(&ic,?rtsp_url,?NULL,?0,?NULL)!=0)??
- ????{?????????????????????????
- ???????? return ?exit_onerr( "can't?open?file." ,-1);??
- ????}??
- ???? if (!ic)??
- ????{??
- ???????? return ?exit_onerr( "unknow?error." ,-2);??
- ????}??
- ????ic?->max_analyze_duration?=?1000;??
- ??
- ???? //get?streams?information ??
- ???? if (av_find_stream_info(ic)<0)??
- ????{??
- ????????av_close_input_file(ic); //退出前,記得釋放資源 ??
- ????????ic?=?NULL;??
- ???????? return ?exit_onerr( "con't?init?streams?information." ,-3);??
- ????}??
- ??
- ??
- ???? //find?stream ??
- ???? int ?videoStream=-1;? //?Didn't?find?a?video?stream ??
- ???? int ?audioStream=-1;? //?Didn't?find?a?audio?stream? ??
- ???? //?Find?the?first?video?stream ??
- ???? for ( int ?i=0;?i<ic?->nb_streams;?i++)??
- ????{??
- ???????? if (?ic?->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO)??
- ????????{???
- ????????????videoStream=i;??
- ???????????? break ;??
- ????????}??
- ????}??
- ???? //?Find?the?first?audio?stream ??
- ???? for ( int ?i=0;?i<ic?->nb_streams;?i++)??
- ????{??
- ???????? if (?ic?->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO)??
- ????????{??
- ????????????audioStream=i;??
- ???????????? break ;??
- ????????}??
- ????}??
- ???? //判斷視頻文件中是否包含音視頻流,如果沒有,退出 ??
- ???? if (audioStream<0?&&?videoStream<0)??
- ????{??
- ????????av_close_input_file(ic); //退出前,記得釋放資源 ??
- ????????ic?=?NULL;??
- ???????? return ?exit_onerr( "con't?find?a?audio?stream?or?video?stream" ,-4);??
- ????}??
- ??
- ???? //open?the?stream?component?for?video ??
- ???? int ?videoComponent?=?-1;??
- ???? if (videoStream?>=?0)??
- ????{??
- ????????videoComponent?=?stream_component_open(ic,?videoStream);???
- ???????? if (videoComponent<0)??
- ????????{??
- ????????????av_close_input_file(ic); //退出前,記得釋放資源 ??
- ???????????? return ?exit_onerr( "not?supported?video?stream" ,-5); //要求重新編譯ffmpeg以支持該種編碼格式 ??
- ????????}??
- ????}??
- ???? //open?the?stream?component?for?audio ??
- ???? int ?audioComponent?=?-1;??
- ???? if (audioStream?>=?0)??
- ????{??
- ????????audioComponent?=?stream_component_open(ic,?audioStream);???
- ???????? if (audioComponent<0)??
- ????????{??
- ????????????av_close_input_file(ic); //退出前,記得釋放資源 ??
- ???????????? return ?exit_onerr( "not?supported?audio?stream" ,-6); //要求重新編譯ffmpeg以支持該種編碼格式 ??
- ????????}??
- ????}??
- ??
- ??
- ???? ////////////////////////////////////////////////////// ??
- ???? int ?ret?=?0;??
- ???? //初始化并打開錄像 ??
- ????AVFormatContext?*?oc?=?NULL;??
- ???? const ? char ?*?out_file_name?=? "D:\\test.avi" ;??
- ??
- ???? //獲取一幀完整的圖像用于初始化ffmpeg內(nèi)部的一些結(jié)構(gòu)體數(shù)據(jù)(這里使用什么數(shù)據(jù)尚未清楚,請自行查看),否則會(huì)出現(xiàn)寫文件頭失敗 ??
- ???? int ?got_picture?=?0;??
- ????AVFrame?*frame?=?avcodec_alloc_frame();??
- ???? while (?1?)??
- ????{??
- ???????? if (av_read_frame(?ic,?&packet)<0)??
- ????????{??
- ????????????av_free_packet(&packet);??
- ????????????av_close_input_file(ic); //退出前,記得釋放資源 ??
- ???????????? return ?exit_onerr( "read?frame?error." ,-7); //讀取視頻幀失敗 ??
- ????????}??
- ???????? if (packet.stream_index?==?videoStream)??
- ????????{??
- ????????????avcodec_decode_video(ic->streams[videoStream]->codec,?frame,?&got_picture,?packet.data,?packet.size);??
- ????????}??
- ????????av_free_packet(&packet);??
- ???????? if (got_picture)??
- ???????????? break ;??
- ????}??
- ????av_free(frame);??
- ??
- ????ret?=?enable_local_record(ic,videoStream,audioStream,&oc,out_file_name, "avi" );??
- ??
- ???? if (ret?<0?||?!oc)??
- ????{??
- ???????? //退出前,記得釋放資源,現(xiàn)在又多了個(gè)oc參數(shù)需要釋放 ??
- ???????? if (oc)??
- ????????{??
- ???????????? ///cleanup?the?output?contents?format ??
- ???????????? for (unsigned? int ?i=0;i<?oc->nb_streams;i++)??
- ????????????{??
- ????????????????av_metadata_free(&oc?->streams[i]->metadata);??
- ????????????????av_free(oc?->streams[i]->codec);??
- ????????????????av_free(oc?->streams[i]);??
- ????????????}??
- ???????????? for (unsigned? int ?i=0;i<oc?->nb_programs;i++)???
- ????????????{??
- ????????????????av_metadata_free(&oc?->programs[i]->metadata);??
- ????????????}??
- ???????????? for (unsigned? int ?i=0;i<oc?->nb_chapters;i++)???
- ????????????{??
- ????????????????av_metadata_free(&oc?->chapters[i]->metadata);??
- ????????????}??
- ????????????av_metadata_free(&oc?->metadata);??
- ????????????av_free(oc);??
- ????????}??
- ????????av_close_input_file(ic);??
- ???????? return ?exit_onerr( "can't?init?out?file." ,-8);??
- ????}??
- ??
- ???? //開始錄像 ??
- ???? int ?video_dts?=?0,audio_dts?=?0; //時(shí)間戳 ??
- ???? int ?total_frame?=?300; //寫300幀文件 ??
- ???? while (total_frame--)??
- ????{??
- ???????? if (?av_read_frame(?ic,?&packet)?<0?)????? //read?the?packet ??
- ????????{?????????
- ???????????? //讀取數(shù)據(jù)出錯(cuò) ??
- ????????????av_free_packet(&packet);??
- ???????????? break ;??
- ????????}??
- ???????? if (packet.data?&&?(packet.stream_index?==?videoStream?||?packet.stream_index?==?audioStream)?)??
- ????????{??
- ???????????? //計(jì)算時(shí)間視頻戳,順序+1,這里可以多研究幾種編碼的音視頻文件,求其時(shí)間戳生成格式,h264編碼順序加1即可 ??
- ???????????? if (packet.stream_index?==?videoStream)??
- ????????????{??
- ????????????????packet.dts?=?video_dts++;??
- ????????????????packet.pts?=?video_dts;??
- ????????????}??
- ???????????? else ? if (packet.stream_index?==?audioStream) //計(jì)算音頻時(shí)間戳 ??
- ????????????{??
- ????????????????packet.dts?=?audio_dts++;??
- ????????????????packet.pts?=?audio_dts?*?(1000?*?packet.size?/ic?->streams[packet.stream_index]->codec?->sample_rate);??
- ????????????}??
- ????????????packet.flags?|=?PKT_FLAG_KEY;??
- ???????????? if (av_interleaved_write_frame(oc,&packet)<0)??
- ????????????{??
- ????????????????printf( "st:%d\twrite?frame?failed.\n" ,packet.stream_index);??
- ????????????}??
- ????????}??
- ????????av_free_packet(&packet);??
- ????}??
- ??
- ???? //關(guān)閉錄像文件和輸入文件 ??
- ??
- ???? //寫文件尾 ??
- ????av_write_trailer(oc);??
- ??
- ???? /*?close?the?output?file?if?need.*/ ??
- ???? if ?(!(oc?->oformat->flags?&?AVFMT_NOFILE))???
- ????{??
- ????????url_fclose(oc->pb);??
- ????}??
- ??
- ???? //釋放資源 ??
- ???? /*cleanup?the?output?contents?format*/ ??
- ???? for (unsigned? int ?i=0;i<?oc->nb_streams;i++)??
- ????{??
- ????????av_metadata_free(&oc?->streams[i]->metadata);??
- ????????av_free(oc?->streams[i]->codec);??
- ????????av_free(oc?->streams[i]);??
- ????}??
- ???? for (unsigned? int ?i=0;i<oc?->nb_programs;i++)???
- ????{??
- ????????av_metadata_free(&oc?->programs[i]->metadata);??
- ????}??
- ???? for (unsigned? int ?i=0;i<oc?->nb_chapters;i++)???
- ????{??
- ????????av_metadata_free(&oc?->chapters[i]->metadata);??
- ????}??
- ????av_metadata_free(&oc?->metadata);??
- ????av_free(oc);??
- ??
- ????av_close_input_file(ic);??
- ??
- ???? return ?0;??
- }??
- ??
- //初始化錄像文件,代碼較長,可寫成函數(shù) ??
- /* ?
- *return?<0??failed,?0?success ?
- */ ??
- int ?enable_local_record(AVFormatContext?*ic /*已經(jīng)打開的視頻文件上下文*/ , int ?videostream, int ?audiostream,AVFormatContext?**out_oc, const ? char ?*?ofile, const ? char ?*?ofileformat)??
- {??
- ????AVFormatContext?*oc?????=?NULL; // ??
- ????AVOutputFormat??*fmt????=?NULL;??
- ??
- ???? if (?ofileformat?)??
- ????{??
- ????????fmt?=?av_guess_format(ofileformat,?NULL,?NULL);??
- ????}??
- ???? if (!fmt)??
- ????{??
- ????????printf( "out?file?format?\"%s\"?invalidate.\n" ,ofileformat);??
- ???????? return ?-1;??
- ????}??
- ??
- ???? /*******************************************init?output?contents?begin**********************************************************/ ??
- ???? /*?allocate?the?output?media?context?*/ ??
- ????oc?=?avformat_alloc_context();??
- ???? if ?(!oc)???
- ????{??
- ????????printf( "out?of?memory.\n" );??
- ???????? return ?-2; //內(nèi)存分配失敗 ??
- ????}??
- ??
- ????*out_oc?=?oc;??
- ??
- ????oc?->oformat?=?fmt;??
- ????sprintf_s(?oc?->filename,? sizeof (?oc?->filename),? "%s" ,?ofile);??
- ????av_metadata_conv(oc,?fmt->metadata_conv,?NULL);??
- ???? if (?videostream?>=0?)??
- ????{??
- ???????? //AVCodecContext*?pCodecCtx=?->streams[videostream]->codec;; ??
- ???????? //add?video?stream ??
- ????????AVStream?*?st?=?av_new_stream(oc,?videostream);??
- ???????? if (!st)??
- ????????{??
- ????????????printf( "can?not?add?a?video?stream.\n" );??
- ???????????? return ?-3;??
- ????????}??
- ????????st->codec->codec_id???????????=??ic?->streams[videostream]?->codec->codec_id;??
- ????????st->codec->codec_type?????=??CODEC_TYPE_VIDEO;??
- ????????st->codec->bit_rate???????????=??ic?->streams[videostream]?->codec->bit_rate;??
- ????????st->codec->width??????????=??ic?->streams[videostream]?->codec->width;??
- ????????st->codec->height?????????=??ic?->streams[videostream]?->codec->height;??
- ????????st->codec->gop_size???????????=??ic?->streams[videostream]?->codec->gop_size;??
- ????????st->codec->pix_fmt????????????=??ic?->streams[videostream]?->codec->pix_fmt;??
- ????????st->codec->frame_size?????=??ic?->streams[videostream]?->codec->frame_size;??
- ????????st->codec->has_b_frames???????=??ic?->streams[videostream]?->codec->has_b_frames;??
- ????????st->codec->extradata??????=??ic?->streams[videostream]?->codec->extradata;??
- ????????st->codec->extradata_size?=??ic?->streams[videostream]?->codec->extradata_size;??
- ????????st->codec->codec_tag??????=??ic?->streams[videostream]?->codec->codec_tag;??
- ????????st->codec->bits_per_raw_sample????????=??ic?->streams[videostream]?->codec->bits_per_raw_sample;??
- ????????st->codec->chroma_sample_location?=??ic?->streams[videostream]?->codec->chroma_sample_location;??
- ????????st->time_base.den????????????=??ic?->streams[videostream]?->time_base.den;??
- ????????st->time_base.num????????????=??ic?->streams[videostream]?->time_base.num;??
- ????????st->cur_dts??????????????????=??ic?->streams[videostream]?->cur_dts;??
- ????????st->stream_copy??????????????=??1;??
- ????????st->pts.den??????????????????=??ic?->streams[videostream]?->time_base.den;??
- ????????st->pts.num??????????????????=??ic?->streams[videostream]?->time_base.num;??
- ???????? if (?oc?->oformat->flags?&?AVFMT_GLOBALHEADER)??
- ????????????st?->codec->flags?|=?CODEC_FLAG_GLOBAL_HEADER;??
- ???????? if (av_q2d(ic?->streams[videostream]?->codec->time_base)*ic?->streams[videostream]?->codec->ticks_per_frame?>?av_q2d(ic?->streams[videostream]->time_base)?&&???
- ????????????av_q2d(ic?->streams[videostream]->time_base)?<?1.0/1000)??
- ????????{??
- ????????????st->codec->time_base?=?ic?->streams[videostream]?->codec->time_base;??
- ????????????st->codec->time_base.num?*=?ic?->streams[videostream]?->codec->ticks_per_frame;??
- ????????}??
- ???????? else ??
- ????????{??
- ????????????st->codec->time_base?=?ic?->streams[videostream]?->time_base;??
- ????????}??
- ????????st->disposition??????????????=??ic?->streams[videostream]?->disposition;??
- ????}??
- ???? if (audiostream?>=?0?)??
- ????{??
- ????????AVStream?*?st?=?av_new_stream(?oc,?audiostream);??
- ???????? if (!st)??
- ????????{??
- ????????????printf( "can?not?add?a?audio?stream.\n" );??
- ???????????? return ?-4;??
- ????????}??
- ????????st->codec->codec_id???????????=??ic?->streams[audiostream]?->codec->codec_id;??
- ????????st->codec->codec_type?????=??CODEC_TYPE_AUDIO;??
- ????????st->codec->bit_rate???????????=??ic?->streams[audiostream]?->codec->bit_rate;??
- ????????st->codec->gop_size???????????=??ic?->streams[audiostream]?->codec->gop_size;??
- ????????st->codec->pix_fmt????????????=??ic?->streams[audiostream]?->codec->pix_fmt;??
- ????????st->codec->bit_rate???????????=??ic?->streams[audiostream]?->codec->bit_rate;??
- ????????st->codec->channel_layout?=??ic?->streams[audiostream]?->codec->channel_layout;??
- ????????st->codec->frame_size?????=??ic?->streams[audiostream]?->codec->frame_size;??
- ????????st->codec->sample_rate????????=??ic?->streams[audiostream]?->codec->sample_rate;??
- ????????st->codec->channels???????????=??ic?->streams[audiostream]?->codec->channels;??????
- ????????st->codec->block_align????????=??ic?->streams[audiostream]?->codec->block_align;???
- ????????st->time_base.den????????????=??ic?->streams[audiostream]?->time_base.den;??
- ????????st->time_base.num????????????=??ic?->streams[audiostream]?->time_base.num;??
- ????????st->stream_copy??????????????=??1;??
- ????????st->pts.den??????????????????=??ic?->streams[audiostream]?->time_base.den;??
- ????????st->pts.num??????????????????=??ic?->streams[audiostream]?->time_base.num;??
- ???????? if (?oc->oformat->flags?&?AVFMT_GLOBALHEADER)??
- ????????????st?->codec->flags?|=?CODEC_FLAG_GLOBAL_HEADER;??
- ???????? if (av_q2d(ic?->streams[audiostream]?->codec->time_base)*ic?->streams[audiostream]?->codec->ticks_per_frame?>?av_q2d(ic?->streams[audiostream]->time_base)?&&???
- ????????????av_q2d(ic?->streams[audiostream]->time_base)?<?1.0/1000)??
- ????????{??
- ????????????st->codec->time_base?=?ic?->streams[audiostream]?->codec->time_base;??
- ????????????st->codec->time_base.num?*=?ic?->streams[audiostream]?->codec->ticks_per_frame;??
- ????????}??
- ???????? else ??
- ????????{??
- ????????????st->codec->time_base?=?ic?->streams[audiostream]?->time_base;??
- ????????}??
- ????}??
- ???? /*?set?the?output?parameters?(must?be?done?even?if?no?parameters).?*/ ??
- ???? //AVFormatParameters?params,?*ap?=??ms; ??
- ???? //memset(ap,?0,?sizeof(*ap)); ??
- ???? if ?(av_set_parameters(oc,?NULL /*ap*/ )?<?0)??
- ????{??
- ????????printf( "invalid?output?format?parameters.\n" );??
- ???????? return ?-5;??
- ????}??
- ????oc?->flags?|=?AVFMT_FLAG_NONBLOCK;??
- ???? /*******************************************init?output?contents?end**********************************************************/ ??
- ??
- ???? /*?open?the?output?file,?if?needed?*/ ??
- ???? if ?(!(oc?->oformat?->flags?&?AVFMT_NOFILE))???
- ????{??
- ???????? try ??
- ????????{??
- ???????????? if ?(url_fopen(&oc->pb,?ofile,?URL_WRONLY)?<?0)???
- ????????????{??
- ????????????????printf( "Could?not?open?file.\n" );??
- ???????????????? return ?-6;??
- ????????????}??
- ????????}??
- ???????? catch (...)??
- ????????{??
- ????????????printf( "Could?not?open?file.\n" );??
- ???????????? return ?-6;??
- ????????}??
- ????}??
- ??
- ???? /*?write?the?stream?header,?if?any?*/ ??
- ???? if (?0?!=?av_write_header(oc))??
- ????{??
- ????????printf( "write?the?stream?header?failed.\n" );??
- ???????? return ?-7;??
- ????}??
- ??
- ???? return ?0;??
- }??
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
