ios 播放ts流视频思路

我们知道FFmpeg能够处理本地文件或者网络文件
只要传入url给avformat_open_input函数就可以了

实际上对于音视频的处理中,
很少会给一个完整有效的网址
很多时候都是传递流信息过来

比如h264 和aac的裸流,这些流只需要调用
ffmpeg 的解码函数即可。

但对于封装格式来说,如何把数据传递给ffmpeg就成了一个很大的问题

我参考雷晓华的内存读取,知道了ffmpeg 提供了某种回调函数

来让外部传入流数据,

    int size = 188000;
    av_register_all();
    avformat_network_init();
    pFormatCtx = avformat_alloc_context();
    unsigned char *aviobuffer=(unsigned char *)av_malloc(size);
    AVIOContext *avio =avio_alloc_context(aviobuffer, size,0,NULL,read_buffer,NULL,NULL);
    pFormatCtx->pb=avio;
    int ret = avformat_open_input(&pFormatCtx,NULL,NULL,NULL);

注意这里面是没有任何地方传递url 的,read_buffer才是ffmpeg读取音视频数据的
地方

int read_buffer(void *opaque, uint8_t *buf, int buf_size){
    int cpSize = 0;
    YYInputQueue *inputQueue = (YYInputQueue *)[(TSDeMuxer *)object getInputQueue];
    while (![(TSDeMuxer *)object stop]) {
        if (inputQueue->getQueueSize()>0) {
            InputStreamData streamData;
            inputQueue->getpacket(streamData);
            memcpy((uint8_t *)buf,streamData.data, streamData.size);
            buf_size = (int )streamData.size;
            printf("input read size=[%d] data=%s\n",buf_size,buf);
            cpSize = buf_size;
            break;
        } else {
            usleep(40*1000);
            continue;
        }
        
    }
    return cpSize;
}

这是从队列里面取出数据,如果数据没有就继续等下去,一直等到数据有为止,


- (void)sendInputDataThread {
    //int perSize = 32768;
    int perSize = 188000;
    FILE *fp_open1=NULL;
    NSFileManager* manager = [NSFileManager defaultManager];
    NSString  *filepath = [[NSBundle mainBundle] pathForResource:@"sdcard" ofType:@"ts"];
    long long size = [[manager attributesOfItemAtPath:filepath error:nil] fileSize];
    int count = (int ) size/perSize;
    fp_open1 = fopen([filepath UTF8String], "r");
    for (int i=0;i<=count;i++) {
        if(!feof(fp_open1)){
            if (self.demuxer.stop) {
                break;
            }
            uint8_t *buf=(uint8_t *)malloc(perSize);;
            int buf_size = perSize;
            if (i== count) {
                buf_size =  size - perSize*count;
            }
            int true_size=fread(buf,1,buf_size,fp_open1);
            if (true_size >0) {
                printf("input write size=[%d] data=%s\n",true_size,buf);
                [self.demuxer sendData:(char *)buf andSize:(int)buf_size andTimeStamp:0];
            }
            usleep(2000*1000);
        }
    }
    fclose(fp_open1);
}

这里是发送数据的代码,可以用来模拟从本地读取文件,
然后切成一片一片的片段,每次读取一段后睡眠一段时间(模拟网络情况)
然后将片段送入队列

readpacket 函数会在队列size大于0 的情况下就返回结果了

剩下的代码就不用写了,和平常的编解码一样了,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值