您的位置:首页 > 理论基础 > 计算机网络

ffmpeg怎么样处理网络流

2014-04-16 10:43 309 查看
http://blog.sina.com.cn/s/blog_675142dc01010otk.html

最近遇到好几个人在问ffmpeg如何处理网络流,刚好前段时间也在做这方面,抽空整理了下,把主要代码发出来,希望对大家有用。为简单处理,我这里只简单介绍UDP接收TS流,其实只要是socket接收的都可以类似处理。

#include "utils.h"

#include <pthread.h>

#include <libavcodec/avcodec.h>

#include <libavformat/avformat.h>

UdpQueue recvqueue;

UdpParam udpParam;

//注册av_read_frame的回调函数,这里只是最简处理,实际应用中应加上出错处理,超时等待...

int read_data(void *opaque, uint8_t *buf, int buf_size) {

int size = buf_size;

int ret;

// printf("read data %d\n", buf_size);

do {

ret = get_queue(&recvqueue, buf, buf_size);

} while (ret);

// printf("read data Ok %d\n", buf_size);

return size;

}

#define BUF_SIZE 4096*500

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

init_queue(&recvqueue, 1024*500);

udpParam.argv = argv;

udpParam.queue = &recvqueue;

uint8_t *buf = av_mallocz(sizeof(uint8_t)*BUF_SIZE);

//UDP接收线程

pthread_t udp_recv_thread;

pthread_create(&udp_recv_thread, NULL, udp_ts_recv,
&udpParam);

pthread_detach(udp_recv_thread);

av_register_all();

AVCodec *pVideoCodec, *pAudioCodec;

AVCodecContext *pVideoCodecCtx = NULL;

AVCodecContext *pAudioCodecCtx = NULL;

AVIOContext * pb = NULL;

AVInputFormat *piFmt = NULL;

AVFormatContext *pFmt = NULL;

//step1:申请一个AVIOContext

pb = avio_alloc_context(buf, BUF_SIZE, 0, NULL, read_data, NULL,
NULL);

if (!pb) {

fprintf(stderr, "avio alloc failed!\n");

return -1;

}

//step2:探测流格式

if (av_probe_input_buffer(pb, &piFmt, "", NULL, 0,
0) < 0) {

fprintf(stderr, "probe failed!\n");

return -1;

} else {

fprintf(stdout, "probe success!\n");

fprintf(stdout, "format: %s[%s]\n", piFmt->name,
piFmt->long_name);

}

pFmt = avformat_alloc_context();

pFmt->pb = pb; //step3:这一步很关键

//step4:打开流

if (avformat_open_input(&pFmt, "", piFmt, NULL)
< 0) {

fprintf(stderr, "avformat open failed.\n");

return -1;

} else {

fprintf(stdout, "open stream success!\n");

}

//以下就和文件处理一致了

if (av_find_stream_info(pFmt) < 0) {

fprintf(stderr, "could not fine stream.\n");

return -1;

}

av_dump_format(pFmt, 0, "", 0);

int videoindex = -1;

int audioindex = -1;

for (int i = 0; i < pFmt->nb_streams;
i++) {

if (
(pFmt->streams[i]->codec->codec_type
== AVMEDIA_TYPE_VIDEO) &&

(videoindex < 0) ) {

videoindex = i;

}

if (
(pFmt->streams[i]->codec->codec_type
== AVMEDIA_TYPE_AUDIO) &&

(audioindex < 0) ) {

audioindex = i;

}

}

if (videoindex < 0 || audioindex <
0) {

fprintf(stderr, "videoindex=%d, audioindex=%d\n", videoindex,
audioindex);

return -1;

}

AVStream *pVst,*pAst;

pVst = pFmt->streams[videoindex];

pAst = pFmt->streams[audioindex];

pVideoCodecCtx = pVst->codec;

pAudioCodecCtx = pAst->codec;

pVideoCodec =
avcodec_find_decoder(pVideoCodecCtx->codec_id);

if (!pVideoCodec) {

fprintf(stderr, "could not find video decoder!\n");

return -1;

}

if (avcodec_open(pVideoCodecCtx, pVideoCodec) < 0)
{

fprintf(stderr, "could not open video codec!\n");

return -1;

}

pAudioCodec =
avcodec_find_decoder(pAudioCodecCtx->codec_id);

if (!pAudioCodec) {

fprintf(stderr, "could not find audio decoder!\n");

return -1;

}

if (avcodec_open(pAudioCodecCtx, pAudioCodec) < 0)
{

fprintf(stderr, "could not open audio codec!\n");

return -1;

}

int got_picture;

uint8_t samples[AVCODEC_MAX_AUDIO_FRAME_SIZE*3/2];

AVFrame *pframe = avcodec_alloc_frame();

AVPacket pkt;

av_init_packet(&pkt);

while(1) {

if (av_read_frame(pFmt, &pkt) >= 0)
{

if (pkt.stream_index == videoindex) {

fprintf(stdout, "pkt.size=%d,pkt.pts=%lld, pkt.data=0x%x.",
pkt.size, pkt.pts,(unsigned int)pkt.data);

avcodec_decode_video2(pVideoCodecCtx, pframe,
&got_picture, &pkt);

if (got_picture) {

fprintf(stdout, "decode one video frame!\n");

}

}else if (pkt.stream_index == audioindex) {

int frame_size = AVCODEC_MAX_AUDIO_FRAME_SIZE*3/2;

if (avcodec_decode_audio3(pAudioCodecCtx, (int16_t *)samples,
&frame_size, &pkt)
>= 0) {

fprintf(stdout, "decode one audio frame!\n");

}

}

av_free_packet(&pkt);

}

}

av_free(buf);

av_free(pframe);

free_queue(&recvqueue);

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: