當前位置:編程學習大全網 - 源碼下載 - 如何使用FFMPEG+H264實現RTP傳輸數據

如何使用FFMPEG+H264實現RTP傳輸數據

開發環境:

WINDOWS7 32bit

MINGW

eclipse juno cdt

1、首先妳要編譯好FFMPEG,

a) 方法壹:可以去官網下載源碼,用MINGW編譯(編譯時記得支持H264,當然,事先得下載並編譯好libx264,視頻技術論壇裏有很多介紹)

b) 方法二:更加省心省力的方法是,下載別人已經編譯好的資源,如ZeranoeFFmpeg的,下載他的dev版本,包含了頭文件,鏈接庫等必須的東西,當然,這東西已經是支持H264的了。

2、以下的就是代碼部分了:

a) 先聲明必要的變量:

AVFormatContext *fmtctx;

AVStream *video_st;

AVCodec *video_codec;

const int FPS = 25; /* 25 images/s */

const char *RDIP = “127.0.0.1”;

unsigned int RDPORT = 5678;

const unsigned int OUTWIDTH = 720;

const unsigned int OUTHEIGHT = 480;

av_register_all();

avformat_network_init();

b) 初始化AV容器

fmtctx = avformat_alloc_context();

c) 獲得輸出格式,這裏是RTP網絡流

fmtctx->oformat = av_guess_format("rtp", NULL, NULL);

d)打開網絡流

snprintf(fmtctx->filename, sizeof(fmtctx->filename),"rtp://%s:%d",RDIP,RDPORT);

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

e) 開始添加H264視頻流

video_st = NULL;video_st = add_video_stream(fmtctx, &video_codec, AV_CODEC_ID_H264);

其中,add_video_stream函數為:

add_video_stream(AVFormatContext *oc,AVCodec **codec, enum AVCodecID codec_id)

{

AVCodecContext *c;

AVStream *st;

/* find the video encoder */

*codec = avcodec_find_encoder(codec_id);

st = avformat_new_stream(oc, *codec);

c = st->codec;

avcodec_get_context_defaults3(c, *codec);

c->codec_id = codec_id;

c->width = OUTWIDTH;

c->height = OUTHEIGHT;

c->time_base.den = FPS;

c->time_base.num = 1;

c->pix_fmt = PIX_FMT_YUV420P;

if(oc->oformat->flags & AVFMT_GLOBALHEADER)

c->flags|= CODEC_FLAG_GLOBAL_HEADER;

av_opt_set(c->priv_data, "preset", "ultrafast", 0);

av_opt_set(c->priv_data, "tune","stillimage,fastdecode,zerolatency",0);

av_opt_set(c->priv_data, "x264opts","crf=26:vbv-maxrate=728:vbv-bufsize=364:keyint=25",0);return st;}

// OPEN THE CODE

avcodec_open2(video_st->codec, video_codec, NULL);

/* Write the stream header, if any. */

avformat_write_header(fmtctx, NULL);

f) 現在,就可以不斷的編碼數據,並發生數據了

AVFrame* m_pYUVFrame = avcodec_alloc_frame();

while(1) //這裏設置成無限循環,妳可以設置成250,或其他數進行測試,觀看結果

{

fill_yuv_image(m_pYUVFrame, video_st->codec->frame_number,OUTWIDTH, OUTHEIGHT);

/* encode the image */

AVPacket pkt;

int got_output = 0;

av_init_packet(&pkt);

pkt.data = NULL; // packet data will be allocated by the encoder

pkt.size = 0;

pkt.pts = AV_NOPTS_VALUE;

pkt.dts =AV_NOPTS_VALUE;

m_pYUVFrame->pts = video_st->codec->frame_number;

ret = avcodec_encode_video2(c, &pkt,frame, &got_output);

if (ret < 0) {fprintf(stderr, "Error encoding video frame: %s\n", av_err2str(ret));

exit(1);

}

/* If size is zero, it means the image was buffered. */

if (got_output)

{

if (c->coded_frame->key_frame)pkt.flags |= AV_PKT_FLAG_KEY;

pkt.stream_index = st->index;

if (pkt.pts != AV_NOPTS_VALUE )

{

pkt.pts = av_rescale_q(pkt.pts,video_st->codec->time_base, video_st->time_base);

}

if(pkt.dts !=AV_NOPTS_VALUE )

{

pkt.dts = av_rescale_q(pkt.dts,video_st->codec->time_base, video_st->time_base);

}

/* Write the compressed frame to the media file. */

ret = av_interleaved_write_frame(oc,&pkt);

}

else {

ret = 0;

}

}

g) Fill_yuv_image函數:

/* Prepare a dummy image. */

static void fill_yuv_image(AVPicture *pict,int frame_index,int width, int height)

{

int x, y, i;

i = frame_index;

/* Y */

for (y = 0; y < height; y++)

for (x = 0; x < width; x++)

pict->data[0][y * pict->linesize[0] +x] = x + y + i * 3;

/* Cb and Cr */

for (y = 0; y < height / 2; y++)

{

for (x = 0; x < width / 2; x++)

{

pict->data[1][y * pict->linesize[1] +x] = 128 + y + i * 2;

pict->data[2][y * pict->linesize[2] +x] = 64 + x + i * 5;

}

}

}

h) 打印sdp信息,僅需壹次,打印的sdp信息,用在VLC播放器結束網絡視頻流時用到

//打印sdp信息

char sdp[2048];

av_sdp_create(&fmtctx,1, sdp, sizeof(sdp));

printf("%s\n",sdp);

fflush(stdout);

i)最後,做壹些清理工作

avcodec_free_frame(&m_pYUVFrame);

av_write_trailer(fmtctx);

/* Free the streams. */

for (unsigned int i = 0; i< fmtctx->nb_streams;i++)

{

av_freep(&fmtctx->streams->codec);

av_freep(&fmtctx->streams);

}

if(!(fmtctx->oformat->flags& AVFMT_NOFILE))

/* Close the output file. */

avio_close(fmtctx->pb);

/*free the stream */

av_free(fmtctx);

3、編譯代碼,記得添加庫文件,運行壹次代碼,不用死循環,設置不用循環,因為是要讓他打印出sdp文件的信息。得到sdp信息,比如我精簡成如下:

c=IN IP4 127.0.0.1

m=video 56782 RTP/AVP 96

a=rtpmap:96 H264/90000

a=framerate:25

a=fmtp:96 packetization-mode=1

把這些信息保存到壹個文本文件,並改名為sdp後綴,如mySDP.sdp。

4、從官網下載VLC播放器,重新運行上述的代碼,這壹次要循環,具體循環多久,妳自己決定,這壹次是正式測試了。代碼跑起來後,把剛剛的sdp文件用VLC打開,直接把sdp文件拖到VLC播放器中就行了。等待緩沖,就可以看到效果了。

5、代碼中剩掉了出錯檢查部分,請自行添加。

6、關於IP地址,這裏是127.0.0.1,是供本機測試,可以改成制定的接受數據的電腦IP地址,或者廣播地址IP地址。

  • 上一篇:有java混淆器的eclipse插件嗎
  • 下一篇:愛粒子源代碼
  • copyright 2024編程學習大全網