ffmpeg处理网络视频流

转载自:https://blog.csdn.net/xipiaoyouzi/article/details/78563484

#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;
}

猜你喜欢

转载自blog.csdn.net/heibao111728/article/details/83579162