ffplay播放文件数据流方向

数据流:

  1. 文件 --> ByteIOContext中的buffer --> 形成AVPacket放进PacketQueue

  2. 从视频PacketQueue中获取AVPacket --> 视频解码线程 --> AVFrame --> 颜色空间转换 --> SDL_OverLay

  3. 从音频PacketQueue中获取AVPacket --> 音频解码回调 --> audio_buf --> SDL音频缓存

 

  1. 作为数据的生产者, 2 & 3 均为数据消费者;

  注意: 其中PacketQueue中有许多个AVPacket, 只有一个AVFrame, SDL音频缓存可以存储一定量的音频数据

//1. 文件 --> ByteIOContext中的buffer --> 形成AVPacket放进PacketQueue.
//static int decode_thread(void *arg) 代码片段, 功能主要是从底层不断的读
//取AVPacket, 并将其分发进音视频不同的PacketQueue.
for(;;) {
  if (is->abort_request)
     break;
    ...
   ret = av_read_frame(ic, pkt);
   if (ret < 0) {
        if (url_ferror(&ic->pb) == 0) {
           SDL_Delay(100); /* wait for user event */
            continue;
        } else
                break;
    }
    if (pkt->stream_index == is->audio_stream) {
        packet_queue_put(&is->audioq, pkt);
    } else if (pkt->stream_index == is->video_stream) {
        packet_queue_put(&is->videoq, pkt);
    } else if (pkt->stream_index == is->subtitle_stream) {
        packet_queue_put(&is->subtitleq, pkt);
    } else {
        av_free_packet(pkt);
    }
}

//2. 从视频PacketQueue中获取AVPacket --> 视频解码线程 --> AVFrame 
//  --> 颜色空间转换 --> SDL_OverLay
//  视频解码线程片段
static int video_thread(void *arg)
{
    ...
    for(;;) {
        while (is->paused && !is->videoq.abort_request) {
            SDL_Delay(10);
        }
        if (packet_queue_get(&is->videoq, pkt, 1) < 0)
            break;
        /* NOTE: ipts is the PTS of the _first_ picture beginning in
           this packet, if any */
        pts = 0;
        if (pkt->dts != AV_NOPTS_VALUE)
            pts = av_q2d(is->video_st->time_base)*pkt->dts;

            SDL_LockMutex(is->video_decoder_mutex);
            len1 = avcodec_decode_video(is->video_st->codec,
                                        frame, &got_picture,
                                        pkt->data, pkt->size);
            SDL_UnlockMutex(is->video_decoder_mutex);
//            if (len1 < 0)
//                break;
            if (got_picture) {
                if (output_picture2(is, frame, pts) < 0)
                    goto the_end;
            }
        av_free_packet(pkt);
        if (step)
            if (cur_stream)
                stream_pause(cur_stream);
    }
   ...
}

//3. 从音频PacketQueue中获取AVPacket --> 音频解码回调 --> audio_buf --> SDL音频缓存
void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
{
    ...
    while (len > 0) {
        if (is->audio_buf_index >= is->audio_buf_size) {
           audio_size = audio_decode_frame(is, is->audio_buf, &pts);
           if (audio_size < 0) {
                /* if error, just output silence */
               is->audio_buf_size = 1024;
               memset(is->audio_buf, 0, is->audio_buf_size);
           } else {
               if (is->show_audio)
                   update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
               audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size,
                                              pts);
               is->audio_buf_size = audio_size;
           }
           is->audio_buf_index = 0;
        }
        len1 = is->audio_buf_size - is->audio_buf_index;
        if (len1 > len)
            len1 = len;
        memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
        len -= len1;
        stream += len1;
        is->audio_buf_index += len1;
    }
}

 

转载于:https://www.cnblogs.com/hacqing/archive/2012/04/10/2440973.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值