第一,loop: 控制播放次数(当前这次也算在内,也就是最?就是1次了),0表示?限次 。
第二,autoexit:?动退出,也就是播放完成后?动退出 。就是不用自动循环 。
loop条件简化的?常不友好,其意思是:如果loop==1,那么已经播了1次了,?需再seek重新播放 。如果loop不是1,==0,随意,?限次循环;减1后还?于0(--loop),也允许循环 。也就是每次播放完毕后,循环的次数就要减1 。
是否循环播放
如果循环播放,即是将?件seek到起始位置 stream_seek(is, start_time != AV_NOPTS_VALUE ?start_time : 0, 0, 0); 注意,这?讲的的起始位置不?定是从头开始,具体也要看?户是否指定了起始播放位置 。
是否?动退出 。
如果播放完毕?动退出 。
(7)使?av_read_frame读取数据包 。
读取数据包很简单,但要注意传?的packet,av_read_frame不会释放其数据,?是每次都重新申请数据 。注意,内存泄漏问题 。
//读取媒体数据,得到的是?视频分离后、解码前的数据// 调?不会释放pkt的数据,都是要??去释放 ret = av_read_frame(ic, pkt); (8)检测数据是否读取完毕 。
if (ret < 0) {if ((ret == AVERROR_EOF || avio_feof(ic->pb))&& !is->eof){// 插?空包说明码流数据读取完毕了,之前讲解码的时候说过刷空包是为了从解码 器把所有帧都读出来if (is->video_stream >= 0)//插入视频空包packet_queue_put_nullpacket(&is->videoq, is->video_strea m);if (is->audio_stream >= 0)//插入音频空包packet_queue_put_nullpacket(&is->audioq, is->audio_strea m);if (is->subtitle_stream >= 0)//插入字幕空包packet_queue_put_nullpacket(&is->subtitleq, is->subtitle _stream);is->eof = 1;// ?件读取完毕}if (ic->pb && ic->pb->error)break;SDL_LockMutex(wait_mutex);//等待超时时间,运行读取线程 。SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10);SDL_UnlockMutex(wait_mutex);// 继续循环 保证线程的运?,?如要seek到某个位置播放可以继 续响应continue;} else {is->eof = 0;}数据读取完毕后,放对应?频、视频、字幕队列插?“空包”,以通知解码器冲刷buffer,将缓存的所有数据都解出来frame并取出来 。然后继续在for{}循环,直到收到退出命令,或者loop播放,或者seek等操作 。
(9)检测是否在播放范围内 。
播放器可以设置:-ss 起始位置,以及 -t 播放时? 。
//检测是否在播放范围内/* check if packet is in play range specified by user, then queue, o therwise discard */ // 获取流的起始时间 stream_start_time = ic->streams[pkt->stream_index]->start_time; // 获取pack et的时间戳pkt_ts = pkt->pts == AV_NOPTS_VALUE ? pkt->dts : pkt->pts; // 这?的duration是在命令?时?来指定播放?度pkt_in_play_range = duration == AV_NOPTS_VALUE ||(pkt_ts - (stream_start_time != AV_NOPTS_VALUE ? stream_start_ti me : 0)) *av_q2d(ic->streams[pkt->stream_index]->time_base) -(double)(start_time != AV_NOPTS_VALUE ? start_time : 0) / 100000 0<= ((double)duration / 1000000);从流获取的参数说明,如下:
第一,stream_start_time,是从当前流AVStream->start_time获取到的时间,如果没有定义具体的值则默认为AV_NOPTS_VALUE,即该值是?效的;那stream_start_time有意义的就是0值 。也就是说,默认是从0开始 。
第二,pkt_ts,当前packet的时间戳,pts有效就?pts的,pts?效就?dts 。
第三,duration,使?"-t value"指定的播放时?,默认值AV_NOPTS_VALUE,即该值?效不?参考 。
第四,start_time,使?“-ss value”指定播放的起始位置,默认AV_NOPTS_VALUE,即该值?效不?参考 。
pkt_in_play_range的值为0或1 。
当没有指定duration播放时?时,很显然duration == AV_NOPTS_VALUE的逻辑值为1,所以pkt_in_play_range为1 。
当duration被指定(-t value)且有效时,主要判断 。
(pkt_ts - (stream_start_time != AV_NOPTS_VALUE ? stream_start_time : 0)) *av_q2d(ic->streams[pkt->stream_index]->time_base) -(double)(start_time != AV_NOPTS_VALUE ? start_time : 0) / 1000000<= ((double)duration / 1000000);实质就是当前时间戳 pkt_ts - start_time 是否 < duration,这?分为:
stream_start_time是否有效:有效就?实际值,?效就是从0开始 。start_time 是否有效,有效就?实际值,?效就是从0开始 。即是pkt_ts - stream_start_time - start_time < duration 。设置了就有有效值,没设置就默认从0开始 。
(10)将数据插?对应的队列 。
//将?视频数据分别送?相应的queue中 if (pkt->stream_index == is->audio_stream && pkt_in_play_range) {//插入到音频packet队列packet_queue_put(&is->audioq, pkt);} else if (pkt->stream_index == is->video_stream && pkt_in_play_rang e&& !(is->video_st->disposition & AV_DISPOSITION_ATTACHED _PIC)) {//printf("pkt pts:%ld, dts:%ldn", pkt->pts, pkt->dts);//插入到视频packet队列packet_queue_put(&is->videoq, pkt);} else if (pkt->stream_index == is->subtitle_stream && pkt_in_play_r ange) {//插入到字幕packet队列packet_queue_put(&is->subtitleq, pkt);} else {av_packet_unref(pkt);// 不?队列则直接释放数据}
推荐阅读
- 海盐奶茶做法,奶茶的详细做法
- 苏州园林的特点解析
- 关于住宅风水朝向解析
- 电动车电池寿命探究与解析
- 孕囊超过23厘米药流会怎样
- 青岛市|好找工作但对口率超低?汉语言文学专业到底是什么样的呢?
- HttpClient三个超时时间详解
- 负载均衡解析与Nginx实战
- 康熙王朝人物关系结构 康熙王朝人物解析
- 央视|今年以来线下的空调、洗衣机、冰箱都变贵了 央视:均价涨超10%
