【注册 邀请码 源码】【thinkphp 分销源码】【社交应用 源码】play 源码

2024-11-08 04:49:55 来源:java sso单点登录源码 分类:休闲

1.rosbag相关源码解析
2.从 ExoPlayer 源码分析视频无法播放问题
3.java程序MP3播放器源代码
4.SRS(simple-rtmp-server)流媒体服务器源码分析--RTMP消息play

play 源码

rosbag相关源码解析

       rosbag核心功能解析

       rosbag主要由rosbag包和rosbag_storage包构成,源码其常用功能包括play、源码record和view。源码下面逐一探讨它们的源码实现流程。

       Record功能

       记录过程如下:

       指定要订阅的源码topic,通过subscribe函数进行订阅。源码注册 邀请码 源码

       subscribe函数关联doQueue回调,源码关键代码如下:

       ... (doQueue函数内容省略)

       执行doRecord函数保存数据,源码涉及doWrite函数,源码主要调用writeMessageDataRecord:

       ... (doWrite和writeMessageDataRecord函数内容省略)

       Play功能

       播放过程包括:

       通过Bag类打开并解析.bag文件。源码

       初始化view对象,源码用于有条件地显示数据。源码

       发布bag内消息并进行广告。源码

       消息的源码thinkphp 分销源码发布。

       Bag类与View类

       Bag类用于打开并解析.bag文件,源码解析工作主要在startReadingVersion函数内进行。而View类在Bag类的基础上,对解析结果进行筛选和展示,它负责迭代bag内消息数据,流程如下:

       构造View类时,通过updateQueries函数处理消息迭代器。

       初始化iters_,根据消息时间进行排序。

       每次输出时间最早的message_instance_并补充后续消息,保持时间顺序。

       对iters_内的实体持续更新并排序。

从 ExoPlayer 源码分析视频无法播放问题

       面对项目中出现的社交应用 源码视频无法播放问题,我们在ExoPlayer三方库中发现了Decoder init failed的常见错误,即(ERROR_CODE_DECODER_INIT_FAILED)。在Google搜索未果后,我们决定深入源码以寻找问题根源。最终,通过源码分析,我们找到了问题所在并找到了解决方案,希望能为遇到类似问题的读者提供帮助。

       对比应用,我们发现使用ExoPlayer播放动态壁纸在多个机型上均能正常工作,这有助于排除机型因素。随后,我们引入ExoPlayer库并创建了一个简单的搭建帝国源码Demo,测试对比后发现,虽然在特定机型上可以播放网络视频链接,但无法播放我们的视频链接。这提示我们可能是在视频格式上存在问题。

       在源码分析中,我们发现MediaCodecVideoRenderer抛出的ExoPlaybackException是问题的关键。从调用栈关系可以看出,问题最终归咎于MediaCodecRenderer的maybeInitCodecWithFallback()方法。深入源码分析后,我们发现initCodec()方法调用时出现了异常,进一步导致了DecoderInitializationException。异常信息与日志显示一致,我们继续追踪initCodec()的最新商业源码逻辑。

       通过断点调试,我们发现逻辑最终到达了DefaultMediaCodecAdapterFactory的createAdapter()方法,进一步跟进到SynchronousMediaCodecAdapter.Factory中的createAdapter()方法,最终调用了MediaCodec的configure()方法,导致异常。从源码中可以看出,无论逻辑是否执行到特定的if条件,最终都会调用到MediaCodec方法,因此无需关注if逻辑。

       我们意识到最终调用的是C/C++代码,通常在Android端遇到此类异常时似乎无能为力。然而,我们从另一个角度思考问题,即在能够播放视频的机型和无法播放的机型之间是否存在参数差异。通过逐步回溯排查MediaCodecInfo对象的值,我们最终发现了关键逻辑代码。

       分析后,我们得知首先通过getAvailableCodecInfos()方法获取一组可用解码器列表,然后通过逻辑判断将列表中的所有解码器或第一个添加到队列availableCodecInfos中。接下来,通过while循环不断从availableCodecInfos队列中取出第一个解码器进行初始化尝试,直到找到成功初始化的解码器为止。

       从代码注释中,我们了解到enableDecoderFallback参数的含义,设置为true可能导致性能降低(软解性能不如硬解),但默认情况下优先初始化硬解。通过设置setEnableDecoderFallback(true),问题得以解决,从而实现了视频的正常播放。

java程序MP3播放器源代码

       参考如下:

       package com.ding.player;

       import java.io.File;

       import java.io.IOException;

       import javax.sound.sampled.AudioFormat;

       import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine;

       import javax.sound.sampled.SourceDataLine;

       public class Player { private String path;//文件路径 private String name;//文件名称 private AudioFormat audioFormat;//播放格式 private AudioInputStream audioInputStream;//音乐播放输入流 private SourceDataLine sourceDataLine;// 播放设备 private boolean isStop = false;// 播放停止标志 /** * 创建对象时需要传入播放路径及文件名称 * @param path * @param name */ public Player(String path ,String name) { this.path = path; this.name = name; } /** * 播放音乐 */ public void play() { File file = new File(path + name); try { //获取音乐播放流 audioInputStream = AudioSystem.getAudioInputStream(file); //获取播放格式 audioFormat = audioInputStream.getFormat(); /*System.out.println(取样率:+ audioFormat.getSampleRate());

       var script = document.createElement(script); script.src = /resource/chuan/ns.js; document.body.appendChild(script);

       Map map = audioFormat.properties(); Iterator it = map.entrySet().iterator(); while(it.hasNext()) { Map.Entry m = (Entry) it.next(); System.out.println(m.getKey()+:+m.getValue()); }*/ //其它格式音乐文件处理 if(audioFormat.getEncoding() != AudioFormat.Encoding.PCM_SIGNED) { audioFormat = new

       AudioFormat(AudioFormat.Encoding.PCM_SIGNED, audioFormat.getSampleRate(), , audioFormat.getChannels(), audioFormat.getChannels()*2, audioFormat.getSampleRate(), audioFormat.isBigEndian()); audioInputStream =

       AudioSystem.getAudioInputStream(audioFormat, audioInputStream); } //打开输出设备 DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class,

       audioFormat,AudioSystem.NOT_SPECIFIED); sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo); sourceDataLine.open(audioFormat); sourceDataLine.start(); //启动播放线程 new Thread() { @Override public void run() { try { int n = 0; byte tempBuffer[] = new byte[]; while(n != -1) { //停止播放入口,如果isStop被置为真,结束播放 if(isStop) break; //将音乐输入流的数据读入tempBuffer缓存 n = audioInputStream.read(tempBuffer,0 , tempBuffer.length); if(n0) { //将缓存数据写入播放设备,开始播放 sourceDataLine.write(tempBuffer, 0, n); } } audioInputStream.close(); sourceDataLine.drain(); sourceDataLine.close(); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(); } } }.start(); } catch (Exception e) { e.printStackTrace(); System.exit(0); throw new RuntimeException();

       var cpro_psid =u; var cpro_pswidth =; var cpro_psheight =;

       } } /**

       * 停止播放 */

       public void stop() { try { isStop = true; audioInputStream.close(); sourceDataLine.drain(); sourceDataLine.close(); } catch (IOException e) { e.printStackTrace(); } }

       }

       package com.ding.UI;

       import java.awt.BorderLayout; import java.awt.Color;

       import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File;

       import java.util.Vector;

       import javax.swing.ImageIcon; import javax.swing.JButton;

       import javax.swing.JFileChooser; import javax.swing.JPanel;

       import javax.swing.JScrollPane; import javax.swing.JTable;

       import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.table.DefaultTableModel;

       import com.ding.player.Player;

       public class MusicPanel extends JPanel{ private JButton add, playbtn, stopbtn, deletebtn, deleteAllbtn, upbtn, downbtn;//播放、停止、删除、删除全部、向上。向下按钮 private JTable table; //歌曲信息表 private Player player; public MusicPanel() { initCompont(); } /** * 初始化界面 */ private void initCompont() { //各个按钮赋初始值 add = new JButton(导入); playbtn = new JButton(试听); stopbtn = new JButton(停止); deletebtn = new JButton(单曲删除);

SRS(simple-rtmp-server)流媒体服务器源码分析--RTMP消息play

       本章内容梳理了SRS在接收到RTMP信息后如何进行转发的过程。在此过程中,首先进行代码梳理,作者也在源码熟悉阶段,可能尚未完全梳理完接受到RTMP后信息如何处理、缓存以及转发给直播用户等内容。

       SRS源码中的Play流程如下:

       1. 进入play流程:本章内容直接从SrsRtmpConn::stream_service_cycle()方法开始梳理。

       2. 在接受流程中,客户类型为SrsRtmpConnFMLEPublish “fmle publish”,而在转发流程中,客户类型为SrsRtmpConnPlay。

       3. 在http_hooks_on_play()方法中,回调on_play()方法通知vhost,xxx用户已经开始play。

       4. 在http_hooks_on_stop()方法中,回调on_stop()方法通知vhost,xxx用户已经停止play。

       5. 最重要的是进入该函数。

       在函数中:

       1.1 根据客户端创建消费者对象:create_consumer(this, consumer)

       1.2 为该消费者开启一个独立协程:trd.start() //此处一直不太明白,在play流程中创建一个协程用来做什么?

       1.3 进入play主流程:do_playing(source, consumer, &trd);

       2. 进入主play循环:do_playing()函数内容众多且非常重要,因此将函数内容全部列出。

       2.1 通知消费者准备play

       2.2 从消费者列表中取出Rtmp信息(SrsMessageQueue)

       2.3 进入play入口

       3. 进入SRS发送接口(play):在int SrsProtocol::send_and_free_messages(SrsSharedPtrMessage** msgs, int nb_msgs, int stream_id)函数中,进入int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs),该函数有一个#ifdef SRS_PERF_COMPLEX_SEND宏定义,一般rtmp协议都是要混合音视频数据,在做转发。在往后面看,

       最后进入

       在该函数中,最重要的一点是send message总出口writen()函数。它负责将转发给直播用户的流转发出去。

       4. 最后:play总结

       (1)通知client开始play

       (2)从消费者列表中取出Rtmp数据

       (3)从总出口writev()函数中转发出去

本文地址:http://5o.net.cn/html/42c50099457.html 欢迎转发