android - mpeg2 ts OpenMAX ffmpeg

  显示原文与译文双语对照的内容
0 0

设置如下:

  1. 多播服务器 1000 Mbs,UDP,Mpeg2-TS部件 1 ( h.222 ) 流直播电视频道。
  2. 四核 1.5 Ghz安卓 4.2.2 GLES 2.0渲染器。
  3. FFMpeg库。
  4. Eclipse Kepler,Android sdk/ndk,等等 运行于 Windows 8.1.
  5. 输出屏幕 1920 x 1080,我使用的纹理为 2048 x 1024,在每秒 35和 45帧之间得到。

应用:

  1. Renderer线程持续运行并通过在媒体图像准备好时将Fragment上传到gpu来更新单个纹理。
  2. 媒体处理程序线程,从服务器/或者本地存储中下载和处理媒体。
  3. 用于缓冲UDP数据包和将数据包解码为帧的视频 thread(s), 。

我将ffmpeg连接到UDP流,并且包被缓冲并且看起来很好地解码。 数据包缓冲区充足,不在/过流下。 我面临的问题是它似乎是在破坏( 。IE 只播放了 1个帧中的个) 框架。 我明白,我需要区分 I/P/B 框架,但是现在,手向上,我没有提示。 我甚至尝试了一个 hack 来检测我的帧。 而且我只是把画面渲染到不到四分之一的屏幕。 所以我没有用全屏幕解码。

解码的帧也存储在单独的缓冲区中,以剪切页面撕裂。 从 1到 10的缓冲区数也已经更改,但没有显示。

从我发现的OpenMax,它只处理MPeg2-TS部分 3 ( h.264 和 AAC ),但你可以使用自己的解码器。 我知道你可以把自己的解码组件添加到它。 我尝试这个路由还是继续使用ffmpeg是值得的?

这个帧解码器( 只有渲染器在准备好后才转换和缩放帧)/* * 这个函数将在数据包中运行,并一直解码直到一帧就绪,或者超出了数据包


while (packetsUsed[decCurrent])
{
 hack_for_i_frame:
 i = avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packets[decCurrent]);
 packetsUsed[decCurrent] = 0;//finished with this one
 i = packets[decCurrent].flags & 0x0001;
 decCurrent++;
 if (decCurrent> = MAXPACKETS) decCurrent = 0;
 if (frameFinished)
 {
 ready_pFrame = pFrame;
 frameReady = true;//notify renderer
 frameCounter++;
 if (frameCounter>=MAXFRAMES) frameCounter = 0;
 pFrame = pFrames[frameCounter];
 return 0;
 }
 else if (i)
 goto hack_for_i_frame;
}

return 0;

包读取器( 作为一个pthread繁殖) void *mainPacketReader(void *voidptr) { int ;


while ( threadState == TS_RUNNING )
{
 if (packetsUsed[prCurrent])
 {
 LOGE("Packet buffer overflow, dropping packet...");
 av_read_frame( pFormatCtx, &packet );
 }
 else if ( av_read_frame( pFormatCtx, &packets[prCurrent] )> = 0 )
 {
 if ( packets[prCurrent].stream_index == videoStream )
 {
 packetsUsed[prCurrent] = 1;//flag as used
 prCurrent++;
 if ( prCurrent> = MAXPACKETS )
 {
 prCurrent = 0;
 }
 }

//here check if the packet is audio and add to audio buffer
 }
}
return NULL;

渲染函数只是在调用这里函数之前已经绑定了//纹理


if ( frameReady == false ) return;

AVFrame *temp;//set to frame 'not' currently being decoded
temp = ready_pFrame;

sws_scale(sws_ctx,(uint8_t const* const *)temp->data,
 temp->linesize, 0, pCodecCtx->height,
 pFrameRGB->data, pFrameRGB->linesize);

glTexSubImage2D(GL_TEXTURE_2D, 0,
 XPOS, YPOS, WID, HGT,
 GL_RGBA, GL_UNSIGNED_BYTE, buffer);

frameReady = false;

过去,libvlc也有音频同步问题,所以我决定和进行一切工作。

如果有人有关于如何停止视频播放或者其他路由的指针,那将是非常值得感激的。

编辑删除 I-Frame ( 完全无用)的hack 。 将sws_scale函数从渲染器移到数据包解码器。 我只留下了udp包读取器线程。

同时,我还把包读线程和包解码线程的优先级更改为实时。 因为这样做,我不会得到丢弃的包的负载。

时间: 原作者:

0 0

( 最后计算出答案按钮的位置)

I-Frame hack完全没用,并且在渲染器中保存了线程重载,sws_scale被移动到解码线程。

我已经从这里完全移除了 sws_scale,并将每个to帧上传到gpu并使用 fragment 明暗器转换为 rgb 。

在这里有兴趣将YUV转换为RGB的任何人都很简单:

顶点着色引擎


attribute vec4 qt_Vertex;
attribute vec2 qt_InUVCoords;
attribute vec4 qt_InColor;
uniform mat4 qt_OrthoMatrix;

varying vec2 qt_TexCoord0;
varying vec4 qt_OutColor;

void main(void)
{
 gl_Position = qt_OrthoMatrix * qt_Vertex;
 qt_TexCoord0 = qt_InUVCoords;
 qt_OutColor = qt_InColor;
}

fragment 明暗器:


precision mediump float;

uniform sampler2D qt_TextureY;
uniform sampler2D qt_TextureU;
uniform sampler2D qt_TextureV;

varying vec4 qt_OutColor;

varying vec2 qt_TexCoord0;

const float num1 = 1.403;//line 1

const float num2 = 0.344;//line 2
const float num3 = 0.714;

const float num4 = 1.770;//line 3
const float num5 = 1.0;

const float half1 = 0.5;

void main(void)
{
 float y = texture2D(qt_TextureY, qt_TexCoord0).r;
 float u = texture2D(qt_TextureU, qt_TexCoord0).r - half1;
 float v = texture2D(qt_TextureV, qt_TexCoord0).r - half1;

 gl_FragColor = vec4( y + num1 * v,
 y - num2 * u - num3 * v,
 y + num4 * u, num5) * qt_OutColor;
}

原作者:
...