2016-11-27 22 views
3

を作成する - ここでffmpegのは、私はffmpegの使用してエンコードしてストリーミングしようとしているRTPストリーム

は、主にエンコードの例から適応、私のコードです(libavcodecの/はlibavformat構築しZeranoeとMSVC x64のを)、エラー処理が

を削除しました
#include "stdafx.h" 
extern "C" { 
#include <libavformat/avformat.h> 
#include <libavcodec/avcodec.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> 
} 
#pragma comment(lib, "avformat.lib") 
#pragma comment(lib, "avutil.lib") 
#pragma comment(lib, "avcodec.lib") 

int main() { 
    avcodec_register_all(); 
    av_register_all(); 
    avformat_network_init(); 

    AVCodecID codec_id = AV_CODEC_ID_H264; 
    AVCodec *codec; 
    AVCodecContext *c = NULL; 
    int i, ret, x, y, got_output; 
    AVFrame *frame; 
    AVPacket pkt; 

    codec = avcodec_find_encoder(codec_id); 
    c = avcodec_alloc_context3(codec); 

    c->bit_rate = 400000; 
    c->width = 352; 
    c->height = 288; 
    c->time_base.num = 1; 
    c->time_base.den = 25; 
    c->gop_size = 25; 
    c->max_b_frames = 1; 
    c->pix_fmt = AV_PIX_FMT_YUV420P; 
    c->codec_type = AVMEDIA_TYPE_VIDEO; 
    c->flags = CODEC_FLAG_GLOBAL_HEADER; 

    if (codec_id == AV_CODEC_ID_H264) { 
     ret = av_opt_set(c->priv_data, "preset", "ultrafast", 0); 
     ret = av_opt_set(c->priv_data, "tune", "zerolatency", 0); 
    } 

    avcodec_open2(c, codec, NULL) 

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

    AVFormatContext* avfctx; 
    AVOutputFormat* fmt = av_guess_format("rtp", NULL, NULL); 

    ret = avformat_alloc_output_context2(&avfctx, fmt, fmt->name, 
     "rtp://127.0.0.1:49990"); 

    printf("Writing to %s\n", avfctx->filename); 

    avio_open(&avfctx->pb, avfctx->filename, AVIO_FLAG_WRITE) 

    struct AVStream* stream = avformat_new_stream(avfctx, codec); 
    stream->codecpar->bit_rate = 400000; 
    stream->codecpar->width = 352; 
    stream->codecpar->height = 288; 
    stream->codecpar->codec_id = AV_CODEC_ID_H264; 
    stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; 
    stream->time_base.num = 1; 
    stream->time_base.den = 25; 

    avformat_write_header(avfctx, NULL); 
    char buf[200000]; 
    AVFormatContext *ac[] = { avfctx }; 
    av_sdp_create(ac, 1, buf, 20000); 
    printf("sdp:\n%s\n", buf); 
    FILE* fsdp; 
    fopen_s(&fsdp, "test.sdp", "w"); 
    fprintf(fsdp, "%s", buf); 
    fclose(fsdp); 
    system("PAUSE"); 
    system("start "" \"C:\\Program Files (x86)\\VideoLAN\\VLC\\vlc.exe\" test.sdp"); 

    int j = 0; 
    for (i = 0; i < 10000; i++) { 
     av_init_packet(&pkt); 
     pkt.data = NULL; // packet data will be allocated by the encoder 
     pkt.size = 0; 
     fflush(stdout); 
     /* prepare a dummy image */ 
     /* Y */ 
     for (y = 0; y < c->height; y++) { 
      for (x = 0; x < c->width; x++) { 
       frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3; 
      } 
     } 
     /* Cb and Cr */ 
     for (y = 0; y < c->height/2; y++) { 
      for (x = 0; x < c->width/2; x++) { 
       frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2; 
       frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5; 
      } 
     } 
     frame->pts = i; 
     /* encode the image */ 
     ret = avcodec_send_frame(c, frame); 
     ret = avcodec_receive_packet(c, &pkt); 

     if (ret == AVERROR_EOF) { 
      got_output = false; 
      printf("Stream EOF\n"); 
     } else if(ret == AVERROR(EAGAIN)) { 
      got_output = false; 
      printf("Stream EAGAIN\n"); 
     } else { 
      got_output = true; 
     } 

     if (got_output) { 
      printf("Write frame %3d (size=%5d)\n", j++, pkt.size); 
      av_interleaved_write_frame(avfctx, &pkt); 
      av_packet_unref(&pkt); 
     } 

     Sleep(40); 
    } 

    // end 
    ret = avcodec_send_frame(c, NULL); 

    /* get the delayed frames */ 
    for (; ; i++) { 
     fflush(stdout); 
     ret = avcodec_receive_packet(c, &pkt); 
     if (ret == AVERROR_EOF) { 
      printf("Stream EOF\n"); 
      break; 
     } else if (ret == AVERROR(EAGAIN)) { 
      printf("Stream EAGAIN\n"); 
      got_output = false; 
     } else { 
      got_output = true; 
     } 

     if (got_output) { 
      printf("Write frame %3d (size=%5d)\n", j++, pkt.size); 
      av_interleaved_write_frame(avfctx, &pkt); 
      av_packet_unref(&pkt); 
     } 
    } 

    avcodec_close(c); 
    av_free(c); 
    av_freep(&frame->data[0]); 
    av_frame_free(&frame); 
    printf("\n"); 
    system("pause"); 
    return 0; 
} 

しかし、VLC(生成されたSDPファイルで開かれた)はストリームを再生できません。メッセージは繰り返さ

packetizer_h264 warning: waiting for SPS/PPS 
core debug: Buffering <some percent>% 

私が間違って何をやっているが続くこの

core error: ES_OUT_RESET_PCR called 

を持っていますか?

答えて

1

ffmpegのソースに掘るの数時間後、私は解決策を見つけた:

  1. は各av_interleaved_write_frame

今VLCの再生前

  • 使用avformat_write_headerCODEC_FLAG_GLOBAL_HEADERフラグを使用しないでください。ストリームは正しく

  • +0

    コーデック 'AV_CODEC_FLAG_GLOBAL_HEADER'フラグは、マルチプレクサ記述にフラグ' AVFMT_GL OBALHEADER'。 rtpの場合は、設定されていません。 codecparを手動で埋め込むのではなく、 'avcodec_parameters_from_context'を使う方がはるかに優れています。また、起動時に 'avformat_write_header'を一度だけ呼び出す必要があります。それを何度もやり直さなければならない場合、あなたは何か間違っているのです。 –

    +0

    @AndreyTurkin「avcodec_parameters_from_context」を使うように変更しました。しかし、 'avformat_write_header'が何度も呼び出されなければ、VLCはストリームを再生せず(バッファリング0%で止まってしまいます)、gstreamerが遅れます(具体的には' avformat_write_header'がx時間間隔で呼び出されるとgstreamerはx時間(〜1秒まで)、次に先に飛びます。私が間違っていることを知りたい。 – DankMemes

    関連する問題