zoukankan      html  css  js  c++  java
  • ffmpeg h264+ts +udp传输

    http://bbs.csdn.net/topics/370246456

    http://1229363.blog.163.com/blog/static/19743427201001244711137/ ffmpeg windows 下编译

    http://www.360doc.com/content/13/0913/15/13084517_314201133.shtml h264帧边界识别

    http://fs-linux.org/forum.php?mod=viewthread&tid=21&extra=page%3D1&page=2 ffmpeg 转码样例

    http://www.360doc.com/content/09/0427/20/59579_3292893.shtml h264 nal技术

    http://bbs.csdn.net/topics/390217270 qt 范例

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

    /*
     * main.c
     *
     *  Created on: 2011-9-18
     *      Author: wudegang
     */

    #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 ", buf_size);
    do {
    ret = get_queue(&recvqueue, buf, buf_size);
    } while (ret);

    // printf("read data Ok %d ", 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! ");
    return -1;
    }
    //step2:探测流格式
    if (av_probe_input_buffer(pb, &piFmt, "", NULL, 0, 0) < 0) {
    fprintf(stderr, "probe failed! ");
    return -1;
    } else {
    fprintf(stdout, "probe success! ");
    fprintf(stdout, "format: %s[%s] ", 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. ");
    return -1;
    } else {
    fprintf(stdout, "open stream success! ");
    }
    //以下就和文件处理一致了
    if (av_find_stream_info(pFmt) < 0) {
    fprintf(stderr, "could not fine stream. ");
    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 ", 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! ");
    return -1;
    }
    if (avcodec_open(pVideoCodecCtx, pVideoCodec) < 0) {
    fprintf(stderr, "could not open video codec! ");
    return -1;
    }

    pAudioCodec = avcodec_find_decoder(pAudioCodecCtx->codec_id);
    if (!pAudioCodec) {
    fprintf(stderr, "could not find audio decoder! ");
    return -1;
    }
    if (avcodec_open(pAudioCodecCtx, pAudioCodec) < 0) {
    fprintf(stderr, "could not open audio codec! ");
    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! ");
    }
    }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! ");
    }
    }
    av_free_packet(&pkt);
    }
    }

    av_free(buf);
    av_free(pframe);
    free_queue(&recvqueue);
    return 0;
    }

  • 相关阅读:
    udhcpd配置及使用
    射频全网通笔记(附全球频段划分及主要运营商对应表)
    Source Insight教程
    关于学习
    一次OGG ERROR OGG-01091 Unable to open file "./dirdat/th079817" 的问题解决
    mysql建立的一个自动更新组织树案案例
    1055
    了解一个A*数据库的数据
    mysql安装
    通过CONTRAB 执行脚本进行监控
  • 原文地址:https://www.cnblogs.com/pengkunfan/p/3501187.html
Copyright © 2011-2022 走看看