ffmpeg解封装获取数据包

/* header */
//
// Created by Administrator on 2020/2/24.
//

#include <pthread.h>
//
// Created by Administrator on 2020/2/24.
//

#ifndef DECODEAUDIO_DEMUX_H
#define DECODEAUDIO_DEMUX_H

extern "C" {
#include <libavcodec/avcodec.h>
#include <libavutil/avutil.h>

#include <libavformat/avformat.h>
#include <libswresample/swresample.h>
#include <libswscale/swscale.h>
}


class Demux {
public:
    Demux();
    Demux(const char *url_);
    ~Demux();
    void setFile(const char *url);              // 设置文件路径用于ffmpeg打开输入

    int demux();                                // 解封装

    bool exit = false;                          // 入队列标志位

    AVCodecParameters *get_audio_param();       // 获取音频 AVCodecParameters
    AVCodecParameters *get_video_param();       // 获取画面 AVCodecParameters

    int get_audio_index();                      // 获取音频流索引
    int get_video_index();                      // 获取画面流索引

    AVRational get_audio_time_base();           // 当前视频的时间基

    int64_t get_duration();                     // 总时长

    AVPacket *read_frame();                     // 读取每一个包

    int seek(int ts);                           // seek功能

    void close();                               // 释放空间

    pthread_mutex_t seek_mutex;

    AVFormatContext *Format_ctx = nullptr;

private:
    const char* url = nullptr;

    int ret = 0;

    int audio_index = -1;
    int video_index = -1;

    AVCodecParameters *audio_codec_param = nullptr;
    AVCodecParameters *video_codec_param = nullptr;

    AVCodec *codec = nullptr;

    AVCodecContext *codec_ctx = nullptr;

    pthread_mutex_t mutex;
};


#endif //DECODEAUDIO_DEMUX_H


#endif //DECODEAUDIO_DECODE_H


/* source */

//
// Created by Administrator on 2020/2/24.
//

#include "Demux.h"

Demux::Demux() {

    pthread_mutex_init(&mutex, NULL);
    pthread_mutex_init(&seek_mutex, NULL);
    LOGD("demux !初始化!");
}

Demux::Demux(const char *url_) {
    this->url = url_;
}

Demux::~Demux() {
    close();
    LOGD("demux 退出1");
}

void Demux::setFile(const char *url) {
    this->url = url;
    LOGD("url : %s", url);
}

/* 解封装 */
int Demux::demux() {

    /* 初始化格式 -- 注册解封装器 */
    av_register_all();

    /* 打开网络流 */
    avformat_network_init();

    pthread_mutex_lock(&mutex);

    // 为解封装格式上下文分配空间
    Format_ctx = avformat_alloc_context();
    if (!Format_ctx)
    {
        pthread_mutex_unlock(&mutex);

        LOGE("avformat_alloc_context err " );
        return -1;
    }

    // 打开文件输入
    ret = avformat_open_input(&Format_ctx, url, nullptr, nullptr);
    if (ret < 0)
    {
        pthread_mutex_unlock(&mutex);
        char buf[1024] = {0};
        av_strerror(ret, buf, sizeof(buf));
        LOGE("avformat_open_input err, %s", buf);
        return -1;
    }

    // 获取文件流 --  -- 在此就可以获取文件的相关信息
    ret = avformat_find_stream_info(Format_ctx, nullptr);
    if (ret < 0)
    {
        LOGE("avformat_find_stream_info err");
        pthread_mutex_unlock(&mutex);
        return -1;
    }

    // 音频和画面流索引 其他信息流-- 字幕等 查看 enum AVMediaType type
    audio_index = av_find_best_stream(Format_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, nullptr, 0);
    video_index = av_find_best_stream(Format_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);

    audio_codec_param = avcodec_parameters_alloc();
    audio_codec_param = Format_ctx->streams[audio_index]->codecpar;
    if (!audio_codec_param)
    {
        LOGD(" Format_ctx->streams[audio_index]->codecpar err");
        pthread_mutex_unlock(&mutex);
        return -1;
    }
	/*
    video_codec_param = avcodec_parameters_alloc();
    video_codec_param = Format_ctx->streams[video_index]->codecpar;
    if (!video_codec_param)
    {
        LOGD(" Format_ctx->streams[audio_index]->codecpar err");
        pthread_mutex_unlock(&mutex);
        return -1;
    }
	*/
    //LOGD("demux succ");
    pthread_mutex_unlock(&mutex);

    return 0;
}

/* 读取每一个包 */
AVPacket *Demux::read_frame() {

    pthread_mutex_lock(&mutex);
    // 1.为个包分配空间
    AVPacket *pkt = av_packet_alloc();
    if (!Format_ctx)
    {
        pthread_mutex_unlock(&mutex);
        return nullptr;
    }

    // 2.获取
    ret = av_read_frame(Format_ctx, pkt);
    if (ret < 0)
    {
        char buf[1024] = {0};

        av_strerror(ret, buf, sizeof(buf));

        pthread_mutex_unlock(&mutex);

        LOGD("av_read_frame err %s", buf);

        pthread_mutex_unlock(&mutex);
        return nullptr;
    }

    // PTS(Presentation Time Stamp)显示时间戳 DTS(Decoding Time Stamp)解码时间戳 转化毫秒
    if (pkt->stream_index == video_index)
    {
        pkt->pts = pkt->pts*(1000 * (av_q2d(Format_ctx->streams[pkt->stream_index]->time_base)));
        pkt->dts = pkt->dts*(1000 * (av_q2d(Format_ctx->streams[pkt->stream_index]->time_base)));
    }

    pthread_mutex_unlock(&mutex);
    return pkt;

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值