入冬前车辆安全检查:如何在native C显示YUV420格式图像?

来源:百度文库 编辑:偶看新闻 时间:2024/04/28 15:21:43
  • 悠嘻猴

yinhe|设置|提醒|短消息|好友 |任务|退出

积分: 73 , e望: 2 点 , e币: 35 元 , e脉: 0 条 , 用户组: 敏而好学 Ⅱ

  • 帖子
  • 收藏
  • 分享
  • 切换到宽版
我的中心
  • .
  • android技术
  • android问答
  • 优亿专题
  • 优亿人才
  • 优亿市场eoeMarket软件商店
  • 开发者服务
  • 开发者社区BBS
搜索开发者社区
eoe·Android开发者门户 首页 Android 问题&解答 如何在native C显示YUV420格式图像?返回列表 查看: 613|回复: 17 go

[多媒体] 如何在native C显示YUV420格式图像? [复制链接]



lxglxt
  • 发短消息
  • 加为好友
lxglxt 当前离线
阅读权限
20 
注册时间
2010-4-26 
最后登录
2011-4-14 
在线时间
62小时 

业精于勤 Ⅲ

业精于勤 Ⅲ, 积分 178, 距离下一级还需 122 积分
UID
28462 
精华
帖子
28 
e望
0 点 
e币
89 元 
在线时间
62小时 
1# 发表于 2010-12-23 15:08 |只看该作者 |倒序浏览 |打印 .pcb { margin-right: 210px; } 我在做播放器,视频解码后得到了YUV420的数据流。
我目前通过转换为RGB565格式,通过本地C代码输出的。
问题是,格式转换耗时太长,导致视频很慢。
android支持YUV420的,请问如何实现?
请叙述实现思路,蕞好有可参考的代码?
收藏1 分享0 好评0 差评0 我工作,我高兴!
回复 引用

举报 返回顶部



lxglxt
  • 发短消息
  • 加为好友
lxglxt 当前离线
阅读权限
20 
注册时间
2010-4-26 
最后登录
2011-4-14 
在线时间
62小时 

业精于勤 Ⅲ

业精于勤 Ⅲ, 积分 178, 距离下一级还需 122 积分
UID
28462 
精华
帖子
28 
e望
0 点 
e币
89 元 
在线时间
62小时 
2# 发表于 2010-12-28 16:45 |只看该作者 自己顶! 我工作,我高兴!
点评回复 引用

举报 返回顶部



Lolingew
  • 发短消息
  • 加为好友
Lolingew 当前离线
阅读权限
20 
注册时间
2010-12-28 
最后登录
2011-4-6 
在线时间
32小时 

业精于勤 Ⅲ

业精于勤 Ⅲ, 积分 119, 距离下一级还需 181 积分
UID
121409 
精华
帖子
22 
e望
0 点 
e币
66 元 
在线时间
32小时 
3# 发表于 2010-12-28 17:12 |只看该作者 我怎么没觉得支持YUV420……我用FFmpeg的源码做转换工作,但是在java里设置了YUV420字样的东西,放不出视频啊

点评回复 引用

举报 返回顶部



lxglxt
  • 发短消息
  • 加为好友
lxglxt 当前离线
阅读权限
20 
注册时间
2010-4-26 
最后登录
2011-4-14 
在线时间
62小时 

业精于勤 Ⅲ

业精于勤 Ⅲ, 积分 178, 距离下一级还需 122 积分
UID
28462 
精华
帖子
28 
e望
0 点 
e币
89 元 
在线时间
62小时 
4# 发表于 2010-12-30 14:13 |只看该作者 回答楼上的,好象surface在Android2.0以后,只支持RGB565了,之前是支持YUV420的。
但即使这样,Android2.2中,在surfaceflinger层,是支持YUV420的,camera输出大都是YUV啊。
不知道怎样才能实现。 我工作,我高兴!
点评回复 引用

举报 返回顶部



yntnfu
  • 发短消息
  • 加为好友
yntnfu 当前离线
阅读权限
30 
注册时间
2010-8-27 
最后登录
2011-3-31 
在线时间
235小时 

励精图治 Ⅳ

励精图治 Ⅳ, 积分 666, 距离下一级还需 34 积分
UID
88217 
精华
帖子
115 
e望
2 点 
e币
310 元 
在线时间
235小时 
5# 发表于 2010-12-30 14:57 |只看该作者 :loveliness:替楼主顶啊,我也在研究这个问题 我很菜很菜 ,就像一颗大白菜~
点评回复 引用

举报 返回顶部



qggmm
  • 发短消息
  • 加为好友
qggmm 当前离线
阅读权限
200 
注册时间
2010-9-14 
最后登录
2011-4-14 
在线时间
255小时 

帮帮团

UID
92371 
精华
帖子
400 
e望
0 点 
e币
594 元 
在线时间
255小时 
6# 发表于 2010-12-31 16:52 |只看该作者 本帖最后由 qggmm 于 2010-12-31 17:03 编辑

顶顶顶 支持eoe


点评回复 引用

举报 返回顶部



tq09931
  • 发短消息
  • 加为好友
tq09931 当前离线
阅读权限
10 
注册时间
2010-3-27 
最后登录
2011-3-10 
在线时间
21小时 

敏而好学 Ⅱ

敏而好学 Ⅱ, 积分 72, 距离下一级还需 28 积分
UID
24523 
精华
帖子
15 
e望
0 点 
e币
37 元 
在线时间
21小时 
7# 发表于 2011-1-24 14:27 |只看该作者 支持楼主  可否交流 我最近也遇到视频的问题  qq9618926

点评回复 引用

举报 返回顶部



lxglxt
  • 发短消息
  • 加为好友
lxglxt 当前离线
阅读权限
20 
注册时间
2010-4-26 
最后登录
2011-4-14 
在线时间
62小时 

业精于勤 Ⅲ

业精于勤 Ⅲ, 积分 178, 距离下一级还需 122 积分
UID
28462 
精华
帖子
28 
e望
0 点 
e币
89 元 
在线时间
62小时 
8# 发表于 2011-3-1 10:55 |只看该作者 说说我的结果吧,给各位参考!
研究结果,我的三星平台,显示系统支持的是YUV420SP格式,这一类的Framebuffer显示代码一般是于平台有关,是厂商编写的。
谷歌的android,一般的显示格式支持只有RGB565了。
而ffmpeg解码出来,是YUV420P格式。
虽然也是YUV,但是一个是打包格式,一个是平面格式。
所以YUV420P只能是转换为RGB565格式了,差别在于如何高效转换。 我工作,我高兴!
点评回复 引用

举报 返回顶部



lxglxt
  • 发短消息
  • 加为好友
lxglxt 当前离线
阅读权限
20 
注册时间
2010-4-26 
最后登录
2011-4-14 
在线时间
62小时 

业精于勤 Ⅲ

业精于勤 Ⅲ, 积分 178, 距离下一级还需 122 积分
UID
28462 
精华
帖子
28 
e望
0 点 
e币
89 元 
在线时间
62小时 
9# 发表于 2011-3-1 11:02 |只看该作者 上代码,我的显示驱动,显示YUV420SP格式
#define        kBufferCount     2
/*============================================================*/
/**************************************************************************************************/
/*********************************************************************************************/
namespace android {
class Test {
public:
    static const sp& getISurface(const sp& s) {
        return s->getISurface();
    }
};
};

sp client;
sp surface;
sp isurface;
sp heap;
ISurface::BufferHeap bufferheap;

size_t framebuffers[2];
u_int framebufferindex = 0;
/**************************************************************************************************/
/*********************************************************************************************/
int VideoDriver_register(void)
{
    LOGI("%s[%d]", __FUNCTION__, __LINE__);
    // set up the thread-pool
    sp proc(ProcessState::self());
    ProcessState::self()->startThreadPool();

    LOGI("%s[%d]", __FUNCTION__, __LINE__);
    // create a client to surfaceflinger
    client = new SurfaceComposerClient();
    client->setOrientation(0, ISurfaceComposer::eOrientationDefault, 0);

    // create pushbuffer surface
    LOGV("Created SurfaceComposerClient\n");
    surface = client->createSurface(getpid(), 0, 1024, 600, PIXEL_FORMAT_UNKNOWN, ISurfaceComposer::ePushBuffers);
    LOGV("Created SurfaceControl\n");

    client->openTransaction();
    surface->setLayer(100000);
    client->closeTransaction();

    // get to the isurface
    LOGI("get to the isurface");
    isurface = Test::getISurface(surface);
    LOGI("isurface = %p\n", isurface.get());

    return 0;
}

/**************************************************************************************************/
/*********************************************************************************************/
int VideoDriver_sregister(int mWidth, int mHeight)
{
    LOGI("%s[%d]", __FUNCTION__, __LINE__);
    // YUV420 frames are 1.5 bytes/pixel
    heap = new MemoryHeapBase(((mWidth * mHeight * 3) / 2) * kBufferCount);
    if (heap->heapID() < 0)
    {
        LOGE("Error creating frame buffer heap");
        client->setOrientation(0, ISurfaceComposer::eOrientationDefault, 0);
        return -1;
    }

    bufferheap = ISurface::BufferHeap(mWidth, mHeight,
           mWidth, mHeight, PIXEL_FORMAT_CUSTOM_YCbCr_420_SP, heap);  //PIXEL_FORMAT_YCbCr_420_P

    isurface->registerBuffers(bufferheap);

    for (int i = 0; i < 2; i++)
    {
        framebuffers[i] = i * ((mWidth * mHeight * 3) / 2);
        LOGV("Frame buffer [%d]: address 0x%08x, offset 0x%08x\n", i, bufferheap.heap->base(), framebuffers[i]);
    }

    return 0;
}

/**************************************************************************************************/
/*********************************************************************************************/
void VideoDriver_unregister(void)
{
    LOGI("%s[%d]", __FUNCTION__, __LINE__);
    client->setOrientation(0, ISurfaceComposer::eOrientationDefault, 0);
    isurface->unregisterBuffers();
}

/**************************************************************************************************/
/*********************************************************************************************/
void VideoDriver_setOrientation(void)
{
    client->setOrientation(0, ISurfaceComposer::eOrientationDefault, 0);
}

/**************************************************************************************************/
/*********************************************************************************************/
void VideoDriver_mfc_display(unsigned int YPhyAddr, unsigned int CPhyAddr)
{
    memcpy(static_cast(bufferheap.heap->base()) + framebuffers[framebufferindex], &YPhyAddr, sizeof(YPhyAddr));
    memcpy(static_cast(bufferheap.heap->base()) + framebuffers[framebufferindex] + sizeof(YPhyAddr), &(CPhyAddr), sizeof(CPhyAddr));

    isurface->postBuffer(framebuffers[framebufferindex]);
    if (++framebufferindex == kBufferCount) framebufferindex = 0;
}

/**********************************************************************************************************************/
/******************************************---end---*******************************************************************/
/**********************************************************************************************************************/
我工作,我高兴!
点评回复 引用

举报 返回顶部



lxglxt
  • 发短消息
  • 加为好友
lxglxt 当前离线
阅读权限
20 
注册时间
2010-4-26 
最后登录
2011-4-14 
在线时间
62小时 

业精于勤 Ⅲ

业精于勤 Ⅲ, 积分 178, 距离下一级还需 122 积分
UID
28462 
精华
帖子
28 
e望
0 点 
e币
89 元 
在线时间
62小时 
10# 发表于 2011-3-1 11:04 |只看该作者 至于相关说明,别人已经写了,在这里直接转贴出来:

《普通应用使用Surface的方法》

Android的NDK提供了Surface类,可供应用向屏幕绘图,但使用这个类,有很多机关,
如果不注意,代码就不会正常工作。
下面是我们使用的时候遇到的问题与解决方法。

1,在C++代码里要使用Surface类,必须在APK的工程文件Android.mk里增加权限

uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER"
如果没有这句,则创建Surface会失败。

2,创建Surface

//sp client;
client = new SurfaceComposerClient();
// 然后向 Surfaceflinger 申请一个 Surface , surface 类型为 PushBuffers

DisplayInfo dispInfo;
client->getDisplayInfo(0,&dispInfo);

int ok = client->initCheck();

// 创建Surface,颜色为32位;ePushBuffers表示buffer由我们提供
surfaceControl = client->createSurface(getpid(), 0, 800, 600,
PIXEL_FORMAT_RGBA_8888, ISurfaceComposer::ePushBuffers);
if (surfaceControl == NULL) {
return JNI_FALSE;
}

// 设置位置,大小以及Z-order
client->openTransaction();
surfaceControl->setPosition(0, 0);
surfaceControl->setSize(800, 600);
surfaceControl->setLayer(99999);
surfaceControl->show();
client->closeTransaction();

3,获取ISurface对象
// 这一句需要权限,要在surface.h里加入frends class
isurface = Test::getISurface(surfaceControl);
这里使用了一个技巧,具体参见“欺骗编译器取得ISurface对象的方法”

4,注册buffer

static const char* pmem = "/dev/pmem";

// 这一句需要root权限
heap = new MemoryHeapBase(pmem, 800 * 600 * 4);
if (heap->heapID() < 0) {
return JNI_FALSE;
}
sp pmemHeap = new MemoryHeapPmem(heap, 0);
if (pmemHeap->getHeapID() >= 0) {
// pmemHeap->slap();
// heap.clear();
// pmemHeap.clear();
return JNI_FALSE;
}

mBufferHeap = ISurface::BufferHeap(800, 600,
800, 600, PIXEL_FORMAT_BGRA_8888, pmemHeap);

int ret = isurface->registerBuffers(mBufferHeap);
这里,因为要打开/dev/pmem设备文件,因此需要有权限,方法很简单,就是root手机,
然后使用命令
chmod a+rw /dev/pmem
来增加权限。
用完后记得复原,否则可能有安全风险。
在代码里修改权限参见“调用Su命令修改设备文件权限的Java代码”。

5,得到buffer指针
char * bp = static_cast(mBufferHeap.heap->base());

6,向buffer写位图数据,注意要是32位的
具体写的代码请参见“向Surface写位图数据的方法”

7,提交修改,通知Surface Flinger更新屏幕
isurface->postBuffer(0);

这样屏幕上就可以看到显示了。
我工作,我高兴!
点评回复 引用

举报 返回顶部



lxglxt
  • 发短消息
  • 加为好友
lxglxt 当前离线
阅读权限
20 
注册时间
2010-4-26 
最后登录
2011-4-14 
在线时间
62小时 

业精于勤 Ⅲ

业精于勤 Ⅲ, 积分 178, 距离下一级还需 122 积分
UID
28462 
精华
帖子
28 
e望
0 点 
e币
89 元 
在线时间
62小时 
11# 发表于 2011-3-1 11:13 |只看该作者 对于正在使用ffmpeg的朋友,我的建议:
对于多媒体视频,越来越倾向于高清,高分辨率了。
软件解码已经力不从心,尽量利用平台的硬件解码,而且同一平台的显示系统和多媒体解码器的输出格式是兼容的。
软件解码只能解决格式支持与否的问题,反正已经是速度慢了,多一步格式转换也无所谓了! 我工作,我高兴!
点评回复 引用

举报 返回顶部



zhouxiangang
  • 发短消息
  • 加为好友
zhouxiangang 当前离线
阅读权限
20 
注册时间
2010-9-7 
最后登录
2011-4-15 
在线时间
67小时 

业精于勤 Ⅲ

业精于勤 Ⅲ, 积分 130, 距离下一级还需 170 积分
UID
90690 
精华
帖子
e望
0 点 
e币
59 元 
在线时间
67小时 
12# 发表于 2011-3-10 17:35 |只看该作者 你是怎么用上面的代码,请指教一下.

点评回复 引用

举报 返回顶部



lxglxt
  • 发短消息
  • 加为好友
lxglxt 当前离线
阅读权限
20 
注册时间
2010-4-26 
最后登录
2011-4-14 
在线时间
62小时 

业精于勤 Ⅲ

业精于勤 Ⅲ, 积分 178, 距离下一级还需 122 积分
UID
28462 
精华
帖子
28 
e望
0 点 
e币
89 元 
在线时间
62小时 
13# 发表于 2011-3-11 11:07 |只看该作者 我把其它相关代码也贴出来吧,供参考。这样基本就全了,剩下的请自行试验。
package com.lxglxt.mengPlayer;

import android.content.Context;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.MediaController;
import android.widget.MediaController.MediaPlayerControl;

public class mengSurfaceView extends SurfaceView implements SurfaceHolder.Callback
{
        private static final String TAG = "mengSurfaceView";
        private static final String mylibname = "mengJniNative";
    public native int  doVideoRegister(Surface surf);
    public native void doVideoUnregister();
        public native int  doPlayer_setDataSource(String pathname);
        public native int  doPlayer_prepare();
        public native int  doPlayer_start();
        public native void doPlayer_exit();
        public native int  doPlayer_main(String path);
        public native void doPlayer_demoVideo();
        public native void doPlayer_setFill(int flag);

    public SurfaceHolder                 mholder;
        public Surface                                 mSurface;
        private Context                                mContext;
        private MediaController                mMediaController;
        private Thread  mThread;

        static {
                try{
                        Log.d(TAG, "now load lib " + mylibname);
                        System.loadLibrary(mylibname);
                }catch(UnsatisfiedLinkError e){
                    Log.d(TAG, "Couldn't load lib " + mylibname + e.getMessage());
            }
        }

        public mengSurfaceView(Context context) {
                super(context);
                // TODO Auto-generated constructor stub
                mholder = this.getHolder();//获取holder
                mholder.addCallback(this);

                mContext = context;
                attachMediaController();
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width,
                        int height) {
                // TODO Auto-generated method stub
                Log.d(TAG,"surfaceChanged");
                mSurface = holder.getSurface();
                doVideoRegister(mSurface);
        }

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
                // TODO Auto-generated method stub
                Log.d(TAG,"surfaceCreated");
                //here test draw
/*                Canvas canvas = mholder.lockCanvas(null);//获取画布
                Paint mPaint = new Paint();
                mPaint.setColor(Color.RED);
                canvas.drawRect(new RectF(0,0,320,240), mPaint);
                mholder.unlockCanvasAndPost(canvas);//解锁画布,提交画好的图像
*/
//                new Thread(new MyThread()).start();
                mThread = new Thread(new MyThread());
                mThread.start();
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
                // TODO Auto-generated method stub
                Log.d(TAG,"surfaceDestroyed");
                doVideoUnregister();
                doPlayer_exit();
//                mThread.destroy();
        }

    public boolean onTouchEvent(android.view.MotionEvent event) {
                Log.d(TAG,"onTouchEvent");
            if(!mMediaController.isShowing()) {
                        mMediaController.show(3000);
                }
                return true;
    }

    private void attachMediaController() {
            mMediaController = new MediaController(mContext);
        View anchorView = this.getParent() instanceof View ?
                    (View)this.getParent() : this;
        mMediaController.setMediaPlayer(mMediaPlayerControl);
        mMediaController.setAnchorView(anchorView);
        mMediaController.setEnabled(true);
    }

    MediaPlayerControl mMediaPlayerControl = new MediaPlayerControl() {

                @Override
                public boolean canPause() {
                        // TODO Auto-generated method stub
                        Log.d(TAG,"canPause, now is null");
                        return false;
                }

                @Override
                public boolean canSeekBackward() {
                        // TODO Auto-generated method stub
                        Log.d(TAG,"canSeekBackward, now is null");
                        return false;
                }

                @Override
                public boolean canSeekForward() {
                        // TODO Auto-generated method stub
                        Log.d(TAG,"canSeekForward, now is null");
                        return false;
                }

                @Override
                public int getBufferPercentage() {
                        // TODO Auto-generated method stub
                        Log.d(TAG,"getBufferPercentage, now is null");
                        return 0;
                }

                @Override
                public int getCurrentPosition() {
                        // TODO Auto-generated method stub
                        Log.d(TAG,"getCurrentPosition, now is null");
                        return 0;
                }

                @Override
                public int getDuration() {
                        // TODO Auto-generated method stub
                        Log.d(TAG,"getDuration, now is null");
                        return 0;
                }

                @Override
                public boolean isPlaying() {
                        // TODO Auto-generated method stub
                        Log.d(TAG,"isPlaying, now is null");
                        return false;
                }

                @Override
                public void pause() {
                        // TODO Auto-generated method stub
                        Log.d(TAG,"pause, now is null");
                }

                @Override
                public void seekTo(int pos) {
                        // TODO Auto-generated method stub
                        Log.d(TAG,"seekTo, now is null");
                }

                @Override
                public void start() {
                        // TODO Auto-generated method stub
                        Log.d(TAG,"start, now is null");
                }
           
    };

        class MyThread implements Runnable{

                @Override
                public void run() {
                                Log.d(TAG,"MyThread");

                                try {
                                        Thread.sleep(400);
                                        doPlayer_setFill(1);
//                                        doPlayer_demoVideo();
                                        doPlayer_prepare();
                                        doPlayer_start();
                                } catch (InterruptedException e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                }
//                                doDrawSurface();
                }
        }
       
    public void setVideoPath(String filePath) {
            doPlayer_setDataSource(filePath);
        }

}
我工作,我高兴!
点评回复 引用

举报 返回顶部



lxglxt
  • 发短消息
  • 加为好友
lxglxt 当前离线
阅读权限
20 
注册时间
2010-4-26 
最后登录
2011-4-14 
在线时间
62小时 

业精于勤 Ⅲ

业精于勤 Ⅲ, 积分 178, 距离下一级还需 122 积分
UID
28462 
精华
帖子
28 
e望
0 点 
e币
89 元 
在线时间
62小时 
14# 发表于 2011-3-11 11:11 |只看该作者 基本是对显示部分的应用。
java部分,在surfaceChanged中,把句柄传递给了C代码。就完成了所有工作,剩下的都是C部分的工作了。 我工作,我高兴!
点评回复 引用

举报 返回顶部



lxglxt
  • 发短消息
  • 加为好友
lxglxt 当前离线
阅读权限
20 
注册时间
2010-4-26 
最后登录
2011-4-14 
在线时间
62小时 

业精于勤 Ⅲ

业精于勤 Ⅲ, 积分 178, 距离下一级还需 122 积分
UID
28462 
精华
帖子
28 
e望
0 点 
e币
89 元 
在线时间
62小时 
15# 发表于 2011-3-11 11:22 |只看该作者 下面是C代码的显示,只用到3个函数
VideoDriver_getPixels();
VideoDriver_lockSurface();
VideoDriver_unLockSurface();
其中VideoDriver_getPixels得到显示buffer的指针,调用avpicture_fill()将frame和这个buffer联系起来。
这样,对buffer的操作就是直接操作显示buffer了。
每一frame之前要lockSurface。
调用sws_scale()格式转换直接将输出送到了显示buffer里面了。
完成frame后,unLockSurface就可以了。

int MediaPlayer_prepareVideo(void)
{
    int i;
    AVCodecContext  *pCodecCtx;
    AVCodec         *pCodec;

    LOGI("prepareVideo");

    // Find the first video stream
    gmVideoStreamIndex=-1;

    for(i=0; inb_streams; i++)
    {
        if(gpMovieFile->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO && gmVideoStreamIndex<0)
        {
            gmVideoStreamIndex=i;
        }
    }

    if(gmVideoStreamIndex==-1)
    {
        LOGE("Didn't find a video stream");
        return -1; // Didn't find a video stream
    }

    // Get a pointer to the codec context for the video stream
    pCodecCtx = gpMovieFile->streams[gmVideoStreamIndex]->codec;

    // Find the decoder for the video stream
    pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
    if(pCodec==NULL)
    {
        LOGE("Codec not found a video decoder");
        return -1;
    }

    // Open codec
    if(avcodec_open(pCodecCtx, pCodec)<0)
    {
        LOGE("uld not open video codec");
        return -1;
    }

    if(pCodecCtx->time_base.num>1000 && pCodecCtx->time_base.den==1)
    {
        pCodecCtx->time_base.den=1000;
    }
   
    video_frame_delay = 1000000/ av_q2d(gpMovieFile->streams[gmVideoStreamIndex]->r_frame_rate);
    LOGI("video_frame_delay %lf", video_frame_delay);

#ifdef SUPORT_VIDEO_OUT
    gmVideoWidth = pCodecCtx->width;
    gmVideoHeight = pCodecCtx->height;
    gmDuration =  gpMovieFile->duration;

    gpConvertCtx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
                                  pCodecCtx->width, pCodecCtx->height, PIX_FMT_RGB565, SWS_POINT, NULL, NULL, NULL);

    if (gpConvertCtx == NULL)
    {
        LOGE("SwsContext is NULL");
        return -1;
    }

    void* pixels;
    if (VideoDriver_getPixels(pCodecCtx->width, pCodecCtx->height, &pixels) != 0)
    {
        LOGE("VideoDriver_getPixels error");
        return -1;
    }

    gpFrame = avcodec_alloc_frame();
    if (gpFrame == NULL) {
        LOGE("gpFrame alloc error");
        return -1;
    }
    // Assign appropriate parts of buffer to image planes in pFrameRGB
    // Note that pFrameRGB is an AVFrame, but AVFrame is a superset
    // of AVPicture
    avpicture_fill((AVPicture *) gpFrame, (uint8_t *) pixels, PIX_FMT_RGB565, pCodecCtx->width, pCodecCtx->height);
#endif
    return 0;
}


/**************************************************************************************************/
/*********************************************************************************************/
void MediaPlayer_Display(AVFrame* frame)
{
    AVCodecContext  *pCodecCtx;
    int ret;
    int mw, mh, ms;
    int sw, sh;
    void* pbuf;

    if (frame == NULL)
    {
        LOGI("%s input error", __FUNCTION__);
        return;
    }

    // Get a pointer to the codec context for the video stream
    pCodecCtx = gpMovieFile->streams[gmVideoStreamIndex]->codec;
    LOGE("pix_fmt=%d", pCodecCtx->pix_fmt);

    mw = pCodecCtx->width;
    mh = pCodecCtx->height;

    ret = VideoDriver_lockSurface();
    if(ret < 0)
    {
        return;
    }
    pbuf = VideoDriver_getBits();
    ms = VideoDriver_getStride();

    sw = VideoDriver_getWidth();
    sh = VideoDriver_getHeight();
    avpicture_fill((AVPicture *)gpFrame, (uint8_t *)pbuf, PIX_FMT_RGB565, sw, sh);
//    LOGE("data0=%d, line0=%d", (int)gpFrame->data[0], (int)gpFrame->linesize[0]);

    disp_time();
    if (gpConvertCtx == NULL)
    {
        if(gbScreenFill == false)
        {
            LOGI("do ScreenNormal");
            gpConvertCtx = sws_getContext(mw, mh, pCodecCtx->pix_fmt, mw, mh, PIX_FMT_RGB565, SWS_POINT, NULL, NULL, NULL);
        }
        else
        {
            LOGI("do ScreenFill");
            gpConvertCtx = sws_getContext(mw, mh, pCodecCtx->pix_fmt, sw, sh, PIX_FMT_RGB565, SWS_POINT, NULL, NULL, NULL);
        }
    }

//    LOGD("sws_scale");
    ret = sws_scale(gpConvertCtx, frame->data, frame->linesize, 0, mh, gpFrame->data, gpFrame->linesize);
    disp_time();

    VideoDriver_unLockSurface();
}
我工作,我高兴!
点评回复 引用

举报 返回顶部



‹ 上一主题|下一主题
返回列表
高级模式 | 发表帖子 B Color Image Link Quote Code Smilies 验证码 换一个 刷新验证码

公司简介|招贤纳士|联系我们|数据统计Copyright 2009 - 2010 eoeAndroid All Rights Reserved 京ICP备09111574号积分 73, 距离下一级还需 27 积分