[FFmpeg + OpenGL + OpenSL ES]获取视频流avPacket - 1

首先创建video的c++类


video.h

在本类中声明一个线程thread_play        利用此线程获取队列里面的数据

声明一个void play();        来启动线程

#ifndef MYMUSIC_WLVIDEO_H
#define MYMUSIC_WLVIDEO_H

#include "WlQueue.h"
#include "WlCallJava.h"

extern "C"
{
#include <libavcodec/avcodec.h>
};

class WlVideo {

public:
    //视频流的索引
    int streamIndex = -1;
    //解码器上下文
    AVCodecContext *avCodecContext = NULL;
    //解码器属性
    AVCodecParameters *codecpar = NULL;
    //队列存储avPacket
    WlQueue *queue = NULL;
    WlPlaystatus *playstatus = NULL;
    //回调java方法的类
    WlCallJava *wlCallJava = NULL;
    AVRational time_base;

    pthread_t thread_play;

public:
    WlVideo(WlPlaystatus *playstatus, WlCallJava *wlCallJava);
    ~WlVideo();

    void play();
};

#endif //MYMUSIC_WLVIDEO_H

video.cpp

#include "WlVideo.h"

WlVideo::WlVideo(WlPlaystatus *playstatus, WlCallJava *wlCallJava) {

    this->playstatus = playstatus;
    this->wlCallJava = wlCallJava;
    //队列初始化
    queue = new WlQueue(playstatus);
}

//回调函数
void * playVideo(void *data)
{

    WlVideo *video = static_cast<WlVideo *>(data);

    while(video->playstatus != NULL && !video->playstatus->exit)
    {
        AVPacket *avPacket = av_packet_alloc();
        if(video->queue->getAvpacket(avPacket) == 0)
        {
            //解码渲染
            LOGE("线程中获取视频AVpacket");
        }
        av_packet_free(&avPacket);
        av_free(avPacket);
        avPacket = NULL;

    }

//不要忘记退出线程
    pthread_exit(&video->thread_play);

}

//播放函数中创建线程  编写回调函数

void WlVideo::play() {

    pthread_create(&thread_play, NULL, playVideo, this);

}

 在        FFmpeg.h        里面声明video对象(不要忘记导包)

WlVideo *video = NULL;

 在        FFmpeg.h        声明一个公共获取解码器上下文的方法

int getCodecContext(AVCodecParameters *codecpar, AVCodecContext **avCodecContext);

在        FFmpeg.cpp        中写方法的实现

int WlFFmpeg::getCodecContext(AVCodecParameters *codecpar, AVCodecContext **avCodecContext) {
    AVCodec *dec = avcodec_find_decoder(codecpar->codec_id);
    if(!dec)
    {
        if(LOG_DEBUG)
        {
            LOGE("can not find decoder");
        }
        callJava->onCallError(CHILD_THREAD, 1003, "can not find decoder");
        exit = true;
        pthread_mutex_unlock(&init_mutex);
        return -1;
    }

    //初始化avCodecContext
    *avCodecContext = avcodec_alloc_context3(dec);
    if(!audio->avCodecContext)
    {
        if(LOG_DEBUG)
        {
            LOGE("can not alloc new decodecctx");
        }
        callJava->onCallError(CHILD_THREAD, 1004, "can not alloc new decodecctx");
        exit = true;
        pthread_mutex_unlock(&init_mutex);
        return -1;
    }

    if(avcodec_parameters_to_context(*avCodecContext, codecpar) < 0)
    {
        if(LOG_DEBUG)
        {
            LOGE("can not fill decodecctx");
        }
        callJava->onCallError(CHILD_THREAD, 1005, "ccan not fill decodecctx");
        exit = true;
        pthread_mutex_unlock(&init_mutex);
        return -1;
    }

    if(avcodec_open2(*avCodecContext, dec, 0) != 0)
    {
        if(LOG_DEBUG)
        {
            LOGE("cant not open audio strames");
        }
        callJava->onCallError(CHILD_THREAD, 1006, "cant not open audio strames");
        exit = true;
        pthread_mutex_unlock(&init_mutex);
        return -1;
    }
    return 0;
}

在        FFmpeg.cpp        void WlFFmpeg::decodeFFmpegThread()         方法        for(int i = 0; i < pFormatCtx->nb_streams; i++)        下获取视频流

else if(pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
        {
            if(video == NULL)
            {
                video = new WlVideo(playstatus, callJava);
                video->streamIndex = i;
                video->codecpar = pFormatCtx->streams[i]->codecpar;
                video->time_base = pFormatCtx->streams[i]->time_base;
            }
        }

/*if(audio != NULL)
    {
        getCodecContext(audio->codecpar, &audio->avCodecContext);
    }*/
//打开视频解码器
    if(video != NULL)
    {
        getCodecContext(video->codecpar, &video->avCodecContext);
    }

在        FFmpeg.cpp        void FFmpeg::start()        方法中        av_read_frame函数下        在这个过程中将avPacket放入队列中

else if(avPacket->stream_index == video->streamIndex)
            {
                video->queue->putAvpacket(avPacket);
            }

 在        FFmpeg.cpp        void FFmpeg::start()        方法中        直接调用

video->play();

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值