2017-09-21 4 views
0

私は実際にネットワーク経由でリアルタイムの画像を効率的に送信しようとしています。このために、私はビデオストリーミングのRTPプロトコルがこれを実現する良い方法だと考えました。ffmpegでRTPに画像を書き込む

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

    #include <libavutil/opt.h> 
    #include <libavutil/channel_layout.h> 
    #include <libavutil/common.h> 
    #include <libavutil/imgutils.h> 
    #include <libavutil/mathematics.h> 
    #include <libavutil/samplefmt.h> 
} 
#include <iostream> 
#include <unistd.h> 
#include <stdio.h> 

//Mainly based on https://stackoverflow.com/questions/40825300/ffmpeg-create-rtp-stream 
int main() 
{ 
    //Init ffmpeg 
    avcodec_register_all(); 
    av_register_all(); 
    avformat_network_init(); 

    //Init the codec used to encode our given image 
    AVCodecID codecID = AV_CODEC_ID_MPEG4; 
    AVCodec* codec; 
    AVCodecContext* codecCtx; 

    codec = avcodec_find_encoder(codecID); 
    codecCtx = avcodec_alloc_context3(codec); 

    //codecCtx->bit_rate  = 400000; 
    codecCtx->width   = 352; 
    codecCtx->height  = 288; 

    codecCtx->time_base.num = 1; 
    codecCtx->time_base.den = 25; 
    codecCtx->gop_size  = 25; 
    codecCtx->max_b_frames = 1; 
    codecCtx->pix_fmt  = AV_PIX_FMT_YUV420P; 
    codecCtx->codec_type = AVMEDIA_TYPE_VIDEO; 

    if (codecID == AV_CODEC_ID_H264) 
    { 
     av_opt_set(codecCtx->priv_data, "preset", "ultrafast", 0); 
     av_opt_set(codecCtx->priv_data, "tune", "zerolatency", 0); 
    } 

    avcodec_open2(codecCtx, codec, NULL); 

    //Init the Frame containing our raw data 
    AVFrame* frame; 

    frame   = av_frame_alloc(); 
    frame->format = codecCtx->pix_fmt; 
    frame->width = codecCtx->width; 
    frame->height = codecCtx->height; 
    av_image_alloc(frame->data, frame->linesize, frame->width, frame->height, codecCtx->pix_fmt, 32); 

    //Init the format context 
    AVFormatContext* fmtCtx = avformat_alloc_context(); 
    AVOutputFormat* format = av_guess_format("rtp", NULL, NULL); 
    avformat_alloc_output_context2(&fmtCtx, format, format->name, "rtp://127.0.0.1:49990"); 

    avio_open(&fmtCtx->pb, fmtCtx->filename, AVIO_FLAG_WRITE); 

    //Configure the AVStream for the output format context 
    struct AVStream* stream  = avformat_new_stream(fmtCtx, codec); 

    avcodec_parameters_from_context(stream->codecpar, codecCtx); 
    stream->time_base.num  = 1; 
    stream->time_base.den  = 25; 

    /* Rewrite the header */ 
    avformat_write_header(fmtCtx, NULL); 

    /* Write a file for VLC */ 
    char buf[200000]; 
    AVFormatContext *ac[] = { fmtCtx }; 
    av_sdp_create(ac, 1, buf, 20000); 
    printf("sdp:\n%s\n", buf); 
    FILE* fsdp = fopen("test.sdp", "w"); 
    fprintf(fsdp, "%s", buf); 
    fclose(fsdp); 

    AVPacket pkt; 
    int j = 0; 
    for(int i = 0; i < 10000; i++) 
    { 
     fflush(stdout); 
     av_init_packet(&pkt); 
     pkt.data = NULL; // packet data will be allocated by the encoder 
     pkt.size = 0; 

     int R, G, B; 
     R = G = B = i % 255; 

     int Y = 0.257 * R + 0.504 * G + 0.098 * B + 16; 
     int U = -0.148 * R - 0.291 * G + 0.439 * B + 128; 
     int V = 0.439 * R - 0.368 * G - 0.071 * B + 128; 

     /* prepare a dummy image */ 
     /* Y */ 
     for (int y = 0; y < codecCtx->height; y++) 
      for (int x = 0; x < codecCtx->width; x++) 
       frame->data[0][y * codecCtx->width + x] = Y; 

     for (int y = 0; y < codecCtx->height/2; y++) 
      for (int x=0; x < codecCtx->width/2; x++) 
      { 
       frame->data[1][y * frame->linesize[1] + x] = U; 
       frame->data[2][y * frame->linesize[2] + x] = V; 
      } 

     /* Which frame is it ? */ 
     frame->pts = i; 

     /* Send the frame to the codec */ 
     avcodec_send_frame(codecCtx, frame); 

     /* Use the data in the codec to the AVPacket */ 
     switch(avcodec_receive_packet(codecCtx, &pkt)) 
     { 
      case AVERROR_EOF: 
       printf("Stream EOF\n"); 
       break; 

      case AVERROR(EAGAIN): 
       printf("Stream EAGAIN\n"); 
       break; 

      default: 
       printf("Write frame %3d (size=%5d)\n", j++, pkt.size); 

       /* Write the data on the packet to the output format */ 
       av_interleaved_write_frame(fmtCtx, &pkt); 

       /* Reset the packet */ 
       av_packet_unref(&pkt); 
       break; 
     } 

     usleep(1e6/25); 
    } 

    // end 
    avcodec_send_frame(codecCtx, NULL); 

    //Free everything 
    av_free(codecCtx); 
    av_free(fmtCtx); 

    return 0; 
} 

をそして私のことができVLCで一つの画像を見ることはなく、ビデオ(私はグレースケールで別の画像を見るためにそれをrealoadしなければならない):

私は実際にこれを試してみました。

誰かがvlcでビデオをうまく再生できない理由を知っていますか?ありがとうございました !

答えて

0

は、多くの研究の後、私はエラーが見つかりました:私は、パケットを正しく配置するために、インターリーブ前

av_packet_rescale_ts(&pkt, codecCtx->time_base, stream->time_base); 

を呼び出すために必要な。どんなに恥...

関連する問題