在android上实现ffmpeg的pipe功能,实现除了file和网络协议以外的流媒体播放
1.ffmpeg支持CONFIG_PIPE_PROTOCOL协议,说白了就是命令管道的使用。
pipe的使用和file的使用是一样的,不同的一点在于file是可以去不断的去读取和seek的,这样在ffmpeg中就会把pipe协议当成一种流媒体来处理。
也就是URLContext->is_streamed的类型。
2.在什么情况下使用ffmpeg的pipe呢?
现在android上最常见的播放流媒体的方式有两种,一种是file的方式,一种就是网络的形式。但是现在类似IPTV的数据处理不是这两种方式,需要实现数据的实时输出。这种是APK通过各种协议把数据处理完以后传递下来的,用传统的两种方式并没有办法管理这些数据,这个时候就需要使用的ffmpeg的pipe功能了。
3.先完成两个可执行文件,完成基于linux下的pipe的动能。
3.1 以下代码实现有名管道的写入功能(TestWriteBin)
#define FIFO_NAME "/data/iptv_hls_pipe"
int main()
{
FILE* file = NULL;
int fifo_fd;
if(access(FIFO_NAME, F_OK) == -1)
{
fifo_fd = mkfifo(FIFO_NAME, 0777);
if(fifo_fd < 0)
{
return 0;
}
}
fifo_fd = open(FIFO_NAME, O_WRONLY);
char* tempBuffer = NULL;
{
file = fopen("/mnt/sdcard/Sample.ts","rb");
if(file == NULL)
{
return -1;
}
tempBuffer = (char*)malloc(1024);
if(tempBuffer == NULL)
{
return -1;
}
while(0==feof(file))
{
size_t n = fread(tempBuffer,1,1024,file);
size_t num =write(fifo_fd, tempBuffer, n);
while (num == -1)
{
num = write(fifo_fd, tempBuffer, n);
}
}
fclose(file);
}
free(tempBuffer);
return 0;
}
3.2 以下代码实现有名管道的读取功能(TestReadBin)
#define FIFO_NAME "/data/iptv_hls_pipe"
int main()
{
FILE* file = NULL;
int fifo_fd;
if(access(FIFO_NAME, F_OK) == -1)
{
fifo_fd = mkfifo(FIFO_NAME, 0666);
if (fifo_fd < 0)
{
return 0;
}
}
fifo_fd = open(FIFO_NAME, O_RDONLY);
char* tempBuffer = NULL;
{
file = fopen("/mnt/sdcard/test_read.ts","a+");
if(file == NULL)
{
return -1;
}
tempBuffer = (char*)malloc(1024);
if(tempBuffer == NULL)
{
return -1;
}
size_t num;
while(num)
{
num = read(fifo_fd,tempBuffer,1024);
if (num > 0)
{
size_t n = fwrite(tempBuffer,1,1024,file);
}
}
}
fclose(file);
free(tempBuffer);
return 0;
}
4.在android4.1上实现基于pipe的mediaplayer播放(TestMediaPlayer)
sp<Surface> mFlingerSurface;
sp<SurfaceComposerClient> mSession;
int main(int argc, char** argv)
{
MediaPlayer *mp = new MediaPlayer();
mSession = new SurfaceComposerClient();
DisplayInfo dinfo;
status_t status = mSession->getDisplayInfo(0, &dinfo);
if (status)
return -1;
// create the native surface
ALOGE("dinfo.w = %d, dinfo.h = %d", dinfo.w, dinfo.h);
sp<SurfaceControl> control = mSession->createSurface(
0, dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);
//4.1的实现
mSession->openGlobalTransaction();
control->setLayer(0x40000000);
mSession->closeGlobalTransaction();
sp<Surface> s = control->getSurface();
//sp<ISurfaceTexture> s = control->getSurfaceTexture();
sp<ProcessState> proc(ProcessState::self());
ProcessState::self()->startThreadPool();
mp->setDataSource("/data/iptv_hls_pipe", NULL);
//mp->setDataSource("/mnt/sdcard/Sample.ts", NULL);
mp->prepare();
mp->setVideoSurfaceTexture(s->getSurfaceTexture()) ;
mp->start();
while(1)
{
usleep(1000000);
}
IPCThreadState::self()->joinThreadPool();
return 0;
}
5.只要实现了TestWriteBin和TestMediaplayer就可以模拟完成类似IPTV流媒体的播放。
有不明白的地方或需要源代码的,欢迎交流。本人QQ:2913712548.
更多相关文章
- Android(安卓)Studio Java代码报红(所有第三方库引入失败),但可正常
- Android(安卓)上多方式定位元素(python)
- Android文件方式建立和读取(properties)方法
- android http 如何使用Put方式进行网络请求
- Android中常用的五种布局方式:LinearLayout
- Android(安卓)Studio如何查看branch列表及切换branch
- android定位方式
- Effective Android设计
- Android批量打包-如何一秒内打几十个apk渠道包