2012-05-23 17 views
21

का उपयोग कर आरटीएसपी स्ट्रीम प्राप्त करना मेरे पास आरटीएसपी का उपयोग कर मेरे लैन स्ट्रीमिंग वीडियो पर आईपी कैमरा है। मैं पर कब्जा है और यह प्रदर्शित करने के लिए सक्षम किया गया है सफलतापूर्वक ffplay आदेश का उपयोग:एफएफएमपीईजी लाइब्रेरी

ffplay rtsp://admin:[email protected]:7070 

(प्रमाणीकरण के साथ)

तो मैं ffmpeg लाइब्रेरी का उपयोग C/C++ में एक ही प्रोग्रामिंग का उपयोग कर प्राप्त करने के लिए करना चाहते हैं। मुझे लगता है कि यह संभव होना चाहिए।

तो मेरे वाक्यांश दो आसान सवालों करते हैं:

  1. कैसे मैं एक C/C++ प्रोग्राम FFMPEG पुस्तकालय का उपयोग करने में धारा प्राप्त होगा? (बस कुछ यूआरएल/ट्यूटोरियल प्रदान करें, क्योंकि Google सहायक नहीं था)

  2. मैं प्राप्त वीडियो कैसे प्रदर्शित करूं? (यहां पर, मुझे निर्देशित करने के लिए कुछ अच्छा यूआरएल)।

उत्तर

28

RTSP के लिए धाराओं निम्नलिखित मेरे लिए काम कर रहा है (एक पीपीएम फाइल करने के लिए फ्रेम मैं परिणाम को बचाने प्राप्त करने के बाद):

#include <stdio.h> 
#include <stdlib.h> 
#include <iostream> 
#include <fstream> 
#include <sstream> 

extern "C" 
{ 
    #include <avcodec.h> 
    #include <avformat.h> 
    #include <avio.h> 
    #include <swscale.h> 
} 

void log_callback(void *ptr, int level, const char *fmt, va_list vargs) 
{ 
    static char message[8192]; 
    const char *module = NULL; 

    if (ptr) 
    { 
     AVClass *avc = *(AVClass**) ptr; 
     module = avc->item_name(ptr); 
    } 
    vsnprintf_s(message, sizeof(message), fmt, vargs); 

    std::cout << "LOG: " << message << std::endl; 
} 


int main(int argc, char** argv) { 

    SwsContext *img_convert_ctx; 
    AVFormatContext* context = avformat_alloc_context(); 
    AVCodecContext* ccontext = avcodec_alloc_context(); 
    int video_stream_index; 

    av_register_all(); 
    avformat_network_init(); 
    //av_log_set_callback(&log_callback); 

    //open rtsp 
    if(avformat_open_input(&context, "rtsp://134.169.178.187:8554/h264.3gp",NULL,NULL) != 0){ 
     return EXIT_FAILURE; 
    } 

    if(avformat_find_stream_info(context,NULL) < 0){ 
     return EXIT_FAILURE; 
    } 

    //search video stream 
    for(int i =0;i<context->nb_streams;i++){ 
     if(context->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) 
      video_stream_index = i; 
    } 

    AVPacket packet; 
    av_init_packet(&packet); 

    //open output file 
    //AVOutputFormat* fmt = av_guess_format(NULL,"test2.mp4",NULL); 
    AVFormatContext* oc = avformat_alloc_context(); 
    //oc->oformat = fmt; 
    //avio_open2(&oc->pb, "test.mp4", AVIO_FLAG_WRITE,NULL,NULL); 

    AVStream* stream=NULL; 
    int cnt = 0; 
    //start reading packets from stream and write them to file 
    av_read_play(context);//play RTSP 

    AVCodec *codec = NULL; 
    codec = avcodec_find_decoder(CODEC_ID_H264); 
    if (!codec) exit(1); 

    avcodec_get_context_defaults3(ccontext, codec); 
    avcodec_copy_context(ccontext,context->streams[video_stream_index]->codec); 
    std::ofstream myfile; 

    if (avcodec_open(ccontext, codec) < 0) exit(1); 

    img_convert_ctx = sws_getContext(ccontext->width, ccontext->height, ccontext->pix_fmt, ccontext->width, ccontext->height, 
          PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL); 

    int size = avpicture_get_size(PIX_FMT_YUV420P, ccontext->width, ccontext->height); 
    uint8_t* picture_buf = (uint8_t*)(av_malloc(size)); 
    AVFrame* pic = avcodec_alloc_frame(); 
    AVFrame* picrgb = avcodec_alloc_frame(); 
    int size2 = avpicture_get_size(PIX_FMT_RGB24, ccontext->width, ccontext->height); 
    uint8_t* picture_buf2 = (uint8_t*)(av_malloc(size2)); 
    avpicture_fill((AVPicture *) pic, picture_buf, PIX_FMT_YUV420P, ccontext->width, ccontext->height); 
    avpicture_fill((AVPicture *) picrgb, picture_buf2, PIX_FMT_RGB24, ccontext->width, ccontext->height); 

    while(av_read_frame(context,&packet)>=0 && cnt <1000) 
    {//read 100 frames 

     std::cout << "1 Frame: " << cnt << std::endl; 
     if(packet.stream_index == video_stream_index){//packet is video 
      std::cout << "2 Is Video" << std::endl; 
      if(stream == NULL) 
      {//create stream in file 
       std::cout << "3 create stream" << std::endl; 
       stream = avformat_new_stream(oc,context->streams[video_stream_index]->codec->codec); 
       avcodec_copy_context(stream->codec,context->streams[video_stream_index]->codec); 
       stream->sample_aspect_ratio = context->streams[video_stream_index]->codec->sample_aspect_ratio; 
      } 
      int check = 0; 
      packet.stream_index = stream->id; 
      std::cout << "4 decoding" << std::endl; 
      int result = avcodec_decode_video2(ccontext, pic, &check, &packet); 
      std::cout << "Bytes decoded " << result << " check " << check << std::endl; 
      if(cnt > 100)//cnt < 0) 
      { 
       sws_scale(img_convert_ctx, pic->data, pic->linesize, 0, ccontext->height, picrgb->data, picrgb->linesize); 
       std::stringstream name; 
       name << "test" << cnt << ".ppm"; 
       myfile.open(name.str()); 
       myfile << "P3 " << ccontext->width << " " << ccontext->height << " 255\n"; 
       for(int y = 0; y < ccontext->height; y++) 
       { 
        for(int x = 0; x < ccontext->width * 3; x++) 
         myfile << (int)(picrgb->data[0] + y * picrgb->linesize[0])[x] << " "; 
       } 
       myfile.close(); 
      } 
      cnt++; 
     } 
     av_free_packet(&packet); 
     av_init_packet(&packet); 
    } 
    av_free(pic); 
    av_free(picrgb); 
    av_free(picture_buf); 
    av_free(picture_buf2); 

    av_read_pause(context); 
    avio_close(oc->pb); 
    avformat_free_context(oc); 

    return (EXIT_SUCCESS); 
} 
+0

उत्तर के लिए धन्यवाद। मैंने [इन] (http://ffmpeg.org/trac/ffmpeg/wiki/UbuntuCompilationGuide) निर्देशों के बाद ffmpeg और x264 स्थापित किया है। स्थापना सफल है और पुस्तकालयों को हमारे यूबंटू सिस्टम के/usr/lib में स्थापित किया गया है। और जब मैं यूआर कोड (/home/bhanu/main.cpp से) का संकलन करने की कोशिश कर रहा हूं लेकिन मुझे उचित झंडे के साथ कुछ समस्याएं आ रही हैं, मुझे लिंकर त्रुटियां मिल रही हैं। मैं उन्हें पोस्ट करूंगा, कृपया मुझे मार्गदर्शन करें कि गलती क्या हो सकती है? –

+0

मैं जिस कमांड का उपयोग कर रहा हूं वह है 'g ++ main.cpp -lavcodec -lavdevice -lavfilter -lavformat -lavutil -logg -lrtmp -lswscale -lx264 -lpthread -lvorbis -L/usr/lib', मुझे निम्न आउटपुट 'मुख्य मिल रहा है .cpp: फ़ंक्शन 'int main (int, char **)': /home/bhanu/work_environment/softwares/ffmpeg/libavformat/allformats.c:49: 'avcodec_register_all' /usr/lib/libavformat के लिए अनिर्धारित संदर्भ ।a (oggparsevorbis.o): फ़ंक्शन 'vorbis_packet' में: संग्रह 2: ld 1 निकास स्थिति ' और कुछ समान त्रुटियों को वापस कर दिया। पूर्ण संकलक आउटपुट के लिए कृपया लिंक [यहां] (http://pastebin.com/B8r3qcti) देखें। –

+0

'cnt <1000) {// 100 फ्रेम पढ़ें 'ऐसा लगता है जैसे कोड 1000 फ्रेम पढ़ता है ... – Pimgd

1

अपने कॉन्फ़िगर फ़ाइल की जाँच करें। armlinux के लिए x86 के लिए इसकी संकलन हो सकती है। thats क्यों आप समाधान है 'avcodec_register_all'

यहाँ करने के लिए अपरिभाषित संदर्भ हो रही है: -

$ cd ffmpeg 

$export LD_RUN_PATH=/usr/local/lib:/usr/lib:/lib 

$ ./configure 

$ make && make install 

और है कि आपके आवेदन संकलन के बाद।

4

एफएफएमपीजी स्थानीय वीडियो फ़ाइलों को खोलने की तरह सीधे आरटीएसपी स्ट्रीम खोल सकता है। Here एक ट्यूटोरियल कोड है जो FFmpeg के नवीनतम संस्करण के साथ अद्यतन करता है।

6

FWIW, मैंने @technique द्वारा प्रदान किए गए कोड को FFMPEG 3.2.2 से प्राप्त पुस्तकालयों के साथ काम करने के लिए अद्यतन किया है। उम्मीद है कि यह किसी को गुगल करने में मदद करता है। कुछ छोटे बदलाव हैं जो इस जवाब पर ठोकर खा रहे लोगों के लिए भ्रमित हो सकते हैं।

#include <stdio.h> 
#include <stdlib.h> 
#include <iostream> 
#include <fstream> 
#include <sstream> 

extern "C" { 
#include <libavcodec/avcodec.h> 
#include <libavformat/avformat.h> 
#include <libavformat/avio.h> 
#include <libswscale/swscale.h> 
} 

int main(int argc, char** argv) { 

    // Open the initial context variables that are needed 
    SwsContext *img_convert_ctx; 
    AVFormatContext* format_ctx = avformat_alloc_context(); 
    AVCodecContext* codec_ctx = NULL; 
    int video_stream_index; 

    // Register everything 
    av_register_all(); 
    avformat_network_init(); 

    //open RTSP 
    if (avformat_open_input(&format_ctx, "rtsp://134.169.178.187:8554/h264.3gp", 
      NULL, NULL) != 0) { 
     return EXIT_FAILURE; 
    } 

    if (avformat_find_stream_info(format_ctx, NULL) < 0) { 
     return EXIT_FAILURE; 
    } 

    //search video stream 
    for (int i = 0; i < format_ctx->nb_streams; i++) { 
     if (format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) 
      video_stream_index = i; 
    } 

    AVPacket packet; 
    av_init_packet(&packet); 

    //open output file 
    AVFormatContext* output_ctx = avformat_alloc_context(); 

    AVStream* stream = NULL; 
    int cnt = 0; 

    //start reading packets from stream and write them to file 
    av_read_play(format_ctx); //play RTSP 

    // Get the codec 
    AVCodec *codec = NULL; 
    codec = avcodec_find_decoder(AV_CODEC_ID_H264); 
    if (!codec) { 
     exit(1); 
    } 

    // Add this to allocate the context by codec 
    codec_ctx = avcodec_alloc_context3(codec); 

    avcodec_get_context_defaults3(codec_ctx, codec); 
    avcodec_copy_context(codec_ctx, format_ctx->streams[video_stream_index]->codec); 
    std::ofstream output_file; 

    if (avcodec_open2(codec_ctx, codec, NULL) < 0) 
     exit(1); 

    img_convert_ctx = sws_getContext(codec_ctx->width, codec_ctx->height, 
      codec_ctx->pix_fmt, codec_ctx->width, codec_ctx->height, AV_PIX_FMT_RGB24, 
      SWS_BICUBIC, NULL, NULL, NULL); 

    int size = avpicture_get_size(AV_PIX_FMT_YUV420P, codec_ctx->width, 
      codec_ctx->height); 
    uint8_t* picture_buffer = (uint8_t*) (av_malloc(size)); 
    AVFrame* picture = av_frame_alloc(); 
    AVFrame* picture_rgb = av_frame_alloc(); 
    int size2 = avpicture_get_size(AV_PIX_FMT_RGB24, codec_ctx->width, 
      codec_ctx->height); 
    uint8_t* picture_buffer_2 = (uint8_t*) (av_malloc(size2)); 
    avpicture_fill((AVPicture *) picture, picture_buffer, AV_PIX_FMT_YUV420P, 
      codec_ctx->width, codec_ctx->height); 
    avpicture_fill((AVPicture *) picture_rgb, picture_buffer_2, AV_PIX_FMT_RGB24, 
      codec_ctx->width, codec_ctx->height); 

    while (av_read_frame(format_ctx, &packet) >= 0 && cnt < 1000) { //read ~ 1000 frames 

     std::cout << "1 Frame: " << cnt << std::endl; 
     if (packet.stream_index == video_stream_index) { //packet is video 
      std::cout << "2 Is Video" << std::endl; 
      if (stream == NULL) { //create stream in file 
       std::cout << "3 create stream" << std::endl; 
       stream = avformat_new_stream(output_ctx, 
         format_ctx->streams[video_stream_index]->codec->codec); 
       avcodec_copy_context(stream->codec, 
         format_ctx->streams[video_stream_index]->codec); 
       stream->sample_aspect_ratio = 
         format_ctx->streams[video_stream_index]->codec->sample_aspect_ratio; 
      } 
      int check = 0; 
      packet.stream_index = stream->id; 
      std::cout << "4 decoding" << std::endl; 
      int result = avcodec_decode_video2(codec_ctx, picture, &check, &packet); 
      std::cout << "Bytes decoded " << result << " check " << check 
        << std::endl; 
      if (cnt > 100) //cnt < 0) 
        { 
       sws_scale(img_convert_ctx, picture->data, picture->linesize, 0, 
         codec_ctx->height, picture_rgb->data, picture_rgb->linesize); 
       std::stringstream file_name; 
       file_name << "test" << cnt << ".ppm"; 
       output_file.open(file_name.str().c_str()); 
       output_file << "P3 " << codec_ctx->width << " " << codec_ctx->height 
         << " 255\n"; 
       for (int y = 0; y < codec_ctx->height; y++) { 
        for (int x = 0; x < codec_ctx->width * 3; x++) 
         output_file 
           << (int) (picture_rgb->data[0] 
             + y * picture_rgb->linesize[0])[x] << " "; 
       } 
       output_file.close(); 
      } 
      cnt++; 
     } 
     av_free_packet(&packet); 
     av_init_packet(&packet); 
    } 
    av_free(picture); 
    av_free(picture_rgb); 
    av_free(picture_buffer); 
    av_free(picture_buffer_2); 

    av_read_pause(format_ctx); 
    avio_close(output_ctx->pb); 
    avformat_free_context(output_ctx); 

    return (EXIT_SUCCESS); 
} 

यह के प्रभाव के लिए कुछ द्वारा संकलित किया जा सकता:

g++ -w my_streamer.cpp -o my_streamer $(pkg-config --cflags --libs libavformat libswscale) 

मैं -w शामिल के बाद से वहाँ पुस्तकालय में इन कार्यों के लिए प्रतिवाद चेतावनी के एक बहुत हैं। आपको pkg-config के साथ-साथ libavformat और libswscale लाइब्रेरी स्थापित करने की आवश्यकता होगी।

+0

आपके अपडेट के बाद से कुछ चीजें बदल गई हैं। कृपया एक नया संस्करण जोड़ने पर विचार करें। धन्यवाद :-) –