xingzilong
2017-08-17 5ce6085328a841e270c7ce1ddfdd36efabf0b095
h264裸数据读取

git-svn-id: http://192.168.1.226/svn/proxy@1018 454eff88-639b-444f-9e54-f578c98de674
3个文件已添加
490 ■■■■■ 已修改文件
RtspFace/PL_AndroidMediaCodecFileFrame.cpp 378 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
RtspFace/PL_AndroidMediaCodecFileFrame.h 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
RtspFace/my_timer.hpp 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
RtspFace/PL_AndroidMediaCodecFileFrame.cpp
New file
@@ -0,0 +1,378 @@
#include "PL_AndroidMediaCodecFileFrame.h"
#include "MaterialBuffer.h"
#include "logger.h"
#include "MediaHelper.h"
#include <media/NdkMediaCodec.h>
#include <media/NdkMediaFormat.h>
#include <android/bitmap.h>
#include "my_timer.hpp"
#include <stdlib.h>
#include <fstream>
using namespace std;
#include <liveMedia/liveMedia.hh>
#define H264_HEAD "01"
struct PL_AMCE_Internal
{
    uint8_t buffer[1920*1080*3];//#todo new from config
    size_t buffSize;
    const size_t buffSizeMax;
    size_t inputFrameCount;
    PL_AndroidMediaCodecFileFrame_Config config;
    AMediaCodec* codec;
    bool payOK;
    MB_Frame tempFrame; // frame for gain
    PL_AMCE_Internal() :
        buffSize(0), buffSizeMax(sizeof(buffer)),
        inputFrameCount(0),
        config(),
        codec(nullptr),
        payOK(false),
        tempFrame()
    {
    }
    ~PL_AMCE_Internal()
    {
    }
    void reset()
    {
        buffSize = 0;
        inputFrameCount = 0;
        PL_AndroidMediaCodecFileFrame_Config _config;
        config = _config;
        codec = nullptr;//#todo destory
        payOK = false;
        MB_Frame _tempFrame;
        tempFrame = _tempFrame;
    }
};
PipeLineElem* create_PL_AndroidMediaCodecFileFrame()
{
    return new PL_AndroidMediaCodecFileFrame;
}
PL_AndroidMediaCodecFileFrame::PL_AndroidMediaCodecFileFrame() : internal(new PL_AMCE_Internal)
,m_b_loop_play(false),m_begin(-1),m_current_time(0)
{
}
PL_AndroidMediaCodecFileFrame::~PL_AndroidMediaCodecFileFrame()
{
    delete (PL_AMCE_Internal*)internal;
    internal= nullptr;
}
bool PL_AndroidMediaCodecFileFrame::init(void* args)
{
    PL_AMCE_Internal* in = (PL_AMCE_Internal*)internal;
    in->reset();
    PL_AndroidMediaCodecFileFrame_Config* config = (PL_AndroidMediaCodecFileFrame_Config*)args;
    int ret = read_file(config->sz_path);
    if(1!=ret)
    {
        LOG_ERROR << "read_file error return length:" <<ret<< LOG_ENDL;
        return false;
    }
    m_b_loop_play = config->b_loop_play;
//    AMediaFormat* format = AMediaFormat_new();
//
//    AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, config->ak_mime.c_str());
//    AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_HEIGHT, config->ak_height);
//    AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_WIDTH, config->ak_width);
//
//    AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, config->ak_bit_rate);
//    AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_FRAME_RATE, config->ak_frame_rate);
//    AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, config->ak_i_frame_interval);
//    //AMediaFormat_setInt32(format, "profile", 0x00000100);
//
//// see: https://developer.android.com/reference/android/media/MediaCodecInfo.CodecCapabilities.html#COLOR_FormatYUV420Flexible
//#define AMEDIA_COLOR_FormatYUV420Flexible 0x7f420888
//    AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_COLOR_FORMAT, config->ak_color_format);
//    //AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_STRIDE, config->ak_width * 2);
//
//    //uint8_t sps[] = {0x0,0x0,0x0,0x1, 0x67, 0x42, 0x00, 0x2A, 0x95, 0xA8, 0x1E, 0x00, 0x89, 0xF9, 0x61, 0x00, 0x00, 0x07, 0x08, 0x00, 0x01, 0x5F, 0x90, 0x04};
//    //uint8_t pps[] = {0x0,0x0,0x0,0x1, 0x68, 0xCE, 0x3C, 0x80};
//    //AMediaFormat_setBuffer(format, "csd-0", sps, sizeof(sps)); // sps
//    //AMediaFormat_setBuffer(format, "csd-1", pps, sizeof(pps)); // pps
//
//    // should like:
//    // mime: string(video/avc), durationUs: int64(10000000), width: int32(480), height: int32(360), max-input-size: int32(55067), csd-0: data, csd-1: data}
//    LOG_INFO << "AMediaFormat_toString: " << AMediaFormat_toString(format) << LOG_ENDL;
//
//    in->codec = AMediaCodec_createEncoderByType(config->ak_mime.c_str());
//
//    if (AMediaCodec_configure(in->codec, format, nullptr, nullptr, AMEDIACODEC_CONFIGURE_FLAG_ENCODE) != AMEDIA_OK)
//    {
//        AMediaFormat_delete(format);
//        LOG_ERROR << "AMediaCodec_configure error" << LOG_ENDL;
//        return false;
//    }
//
//    if (AMediaCodec_start(in->codec) != AMEDIA_OK)
//    {
//        AMediaFormat_delete(format);
//        LOG_ERROR << "AMediaCodec_start error" << LOG_ENDL;
//        return false;
//    }
//
//    AMediaFormat_delete(format);
    return true;
}
void PL_AndroidMediaCodecFileFrame::finit()
{
    PL_AMCE_Internal* in = (PL_AMCE_Internal*)internal;
    //todo release codec
    // call AMediaCodec_stop
}
bool amce_pay_file_frame_breaker(const PipeMaterial* pm, void* args)
{
    PL_AMCE_Internal* in = (PL_AMCE_Internal*)args;
    MB_Frame* frame = (MB_Frame*)pm->buffer;
//    ssize_t bufidx = AMediaCodec_dequeueInputBuffer(in->codec, 2000);
//    LOGP(DEBUG, "input buffer bufidx=%zd, inputFrameCount=%d", bufidx, in->inputFrameCount++);
//
//    if (bufidx >= 0)
//    {
//        size_t bufsize;
//        uint8_t* inputBuff = AMediaCodec_getInputBuffer(in->codec, bufidx, &bufsize);
//        size_t sampleSize = std::min(bufsize, frame->buffSize);
//        memcpy(inputBuff, frame->buffer, sampleSize); // fill buffer
//
//        uint64_t presentationTimeUs = timeval_to_microseconds(frame->pts); //microseconds
//
//        media_status_t ms = AMediaCodec_queueInputBuffer(in->codec, bufidx, 0, sampleSize, presentationTimeUs, 0);
//
//        in->payOK = true;
//        LOGP(DEBUG, "media_status_t=%d", ms);
//    }
//    else
//    {
//        LOG_WARN << "bufidx=" << bufidx << LOG_ENDL;
//        in->payOK = false;
//        return false;
//    }
    return false;
}
bool PL_AndroidMediaCodecFileFrame::pay(const PipeMaterial& pm)
{
    PL_AMCE_Internal* in = (PL_AMCE_Internal*)internal;
    in->payOK = false;
    if (!in->payOK)
        pm.breake(PipeMaterial::PMT_FRAME, MB_Frame::MBFT_NV12, amce_pay_file_frame_breaker, in);
    return in->payOK;
}
bool PL_AndroidMediaCodecFileFrame::gain(PipeMaterial& pm)
{
    PL_AMCE_Internal* in = (PL_AMCE_Internal*)internal;
//    if (!in->payOK)
//    {
//        LOG_WARN << "not in->payOK" << LOG_ENDL;
//        return false;
//    }
    pm.deleter = nullptr;
    pm.former = this;
//    AMediaCodecBufferInfo info;
//    ssize_t outputBuffIdx = AMediaCodec_dequeueOutputBuffer(in->codec, &info, 0);
    //if (outputBuffIdx >= 0)
    {
        string str_buf;
//        LOG_WARN << "hello" << LOG_ENDL;
//        LOGP(WARNING,"hello %s",m_str_context.c_str());
//        LOG_WARN << "world" << LOG_ENDL;
        std::string data({0,0,0,1});
        m_begin = m_str_context.find(data,m_begin+1);
        static int _count = 0;
        char sz_path[256]={0};
        if((m_begin!=string::npos)&&(m_begin!=0)&&(m_begin!=-1))
        {
            my_module_space::Timer _timer;
            long long tmp = _timer.tell_ms()-m_current_time;
            if(tmp<40)
            {
                long long _value = (40-tmp)*1000;
                //usleep(_value);
            }
            m_current_time = _timer.tell_ms();
            str_buf = m_str_context.substr(0, m_begin);
            LOGP(WARNING,"still running...");
//            memset(sz_path,0,256);
//            sprintf(sz_path,"/data/stream_content/%d",_count);
//            write_file(sz_path,str_buf.c_str(),str_buf.length());
//            _count++;
            m_str_context = m_str_context.substr(m_begin, m_str_context.length() - m_begin);
            in->buffSize = std::min(str_buf.length(), in->buffSizeMax);
            memcpy(in->buffer, &str_buf[0], in->buffSize);
            in->tempFrame.type = MB_Frame::MBFT_H264_NALU_AUX;
            in->tempFrame.buffer = in->buffer;
            in->tempFrame.buffSize = in->buffSize;
           // microseconds_to_timeval(info.presentationTimeUs, in->tempFrame.pts);
            pm.type = PipeMaterial::PMT_FRAME;
            pm.buffer = &(in->tempFrame);
            pm.buffSize = 0;
            return true;
        }
        else if((m_begin==string::npos)&&m_b_loop_play)
        {
            m_str_context = m_str_old_context;
        }
    }
//    ssize_t outputBuffIdx = AMediaCodec_dequeueOutputBuffer(in->codec, &info, 0);
//    if (outputBuffIdx >= 0)
//    {
//        if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM)
//        {
//            LOGP(WARNING, "output EOS");
//        }
//
//       //AMediaFormat* format = AMediaCodec_getOutputFormat(in->codec);
//       //if (format != NULL)
//       //{
//       //    int32_t width, height, color;
//       //    AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &width);
//       //    AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &height);
//       //    AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_COLOR_FORMAT, &color);
//       //    AMediaFormat_delete(format);
//       //    format = nullptr;
//       //    LOGP(DEBUG, "output media format, w=%d, h=%d, c=%d", width, height, color);
//       //}
//
//        in->tempFrame.reset();
//
//        size_t outSize = in->buffSizeMax;
//        uint8_t* outputBuff = AMediaCodec_getOutputBuffer(in->codec, outputBuffIdx, &outSize);
//        if (outputBuff != nullptr)
//        {
//            in->buffSize = std::min((size_t) info.size, in->buffSizeMax);
//            memcpy(in->buffer, outputBuff + info.offset, in->buffSize);
//
//            in->tempFrame.type = MB_Frame::MBFT_H264_NALU_AUX;
//            in->tempFrame.buffer = in->buffer;
//            in->tempFrame.buffSize = in->buffSize;
//            in->tempFrame.width = in->config.ak_width;
//            in->tempFrame.height = in->config.ak_height;
//            microseconds_to_timeval(info.presentationTimeUs, in->tempFrame.pts);
//
//            pm.type = PipeMaterial::PMT_FRAME;
//            pm.buffer = &(in->tempFrame);
//            pm.buffSize = 0;
//
//            //static size_t f = 0;
//            //static FILE *pFile = fopen("/data/aa.264", "wb");
//            //fwrite(in->buffer, sizeof(char), in->buffSize, pFile);
//            //if (++f > 400){
//            //    fclose(pFile);
//            //    exit(0);
//            //}
//        }
//
//        AMediaCodec_releaseOutputBuffer(in->codec, outputBuffIdx, false);
//
//        return true;
//    }
//    else if (outputBuffIdx == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED)
//    {
//        LOGP(DEBUG, "output buffers changed");
//    }
//    else if (outputBuffIdx == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED)
//    {
//        auto format = AMediaCodec_getOutputFormat(in->codec);
//        LOGP(INFO, "format changed to: %s", AMediaFormat_toString(format));
//
//        uint8_t* sps = nullptr;
//        size_t spsSize = 0;
//        uint8_t* pps = nullptr;
//        size_t ppsSize = 0;
//
//        AMediaFormat_getBuffer(format, "csd-0", (void**)&sps, &spsSize); // sps
//        AMediaFormat_getBuffer(format, "csd-1", (void**)&pps, &ppsSize); // pps
//
//        if (spsSize != 0)
//        {
//            std::string spsStr = base64_encode(((const char*)sps) + 4, spsSize - 4);//#todo aux
//            std::string ppsStr = base64_encode(((const char*)pps) + 4, ppsSize - 4);
//
//            this->manager->set_param(PLGP_ENC_SPS_B64, spsStr);
//            this->manager->set_param(PLGP_ENC_PPS_B64, ppsStr);
//        }
//
//        AMediaFormat_delete(format);
//    }
//    else if (outputBuffIdx == AMEDIACODEC_INFO_TRY_AGAIN_LATER)
//    {
//        LOGP(DEBUG, "no output buffer right now");
//    }
//    else
//    {
//        LOGP(WARNING, "unexpected info code: %zd", outputBuffIdx);
//    }
    return false;
}
int PL_AndroidMediaCodecFileFrame::write_file(const char* p_path,const char* p_content,int nlength)
{
    std::fstream outfile(p_path, std::ios_base::out | std::ios_base::binary);
    outfile.write(p_content, nlength);
    outfile.close();
}
int PL_AndroidMediaCodecFileFrame::read_file(const char* p_path)
{
    std::fstream infile(p_path, std::ios_base::in | std::ios_base::binary | ios::ate);
    size_t nSize = infile.tellg();
    infile.seekg(0, ios::beg);
    if (nSize <= 0)
    {
        infile.close();
        return nSize;
    }
    m_str_context.resize(nSize);
    infile.read(&(m_str_context[0]), nSize);
    m_str_old_context = m_str_context;
    infile.close();
    return 1;
}
int PL_AndroidMediaCodecFileFrame::analyse_context()
{
    int _count = 0;
    int _begin = -1;
    while((_begin=m_str_context.find(H264_HEAD,_begin+1))!=string::npos)
    {
        _count++;
    }
    return 1;
}
RtspFace/PL_AndroidMediaCodecFileFrame.h
New file
@@ -0,0 +1,47 @@
#ifndef _PL_ANDROIDMEDIACODECFILEFRAME_H_
#define _PL_ANDROIDMEDIACODECFILEFRAME_H_
#include "PipeLine.h"
struct PL_AndroidMediaCodecFileFrame_Config
{
    char  sz_path[256];
    bool  b_loop_play;
    PL_AndroidMediaCodecFileFrame_Config() :
            b_loop_play(false)
    {
        memset(sz_path,0,256);
    }
};
class PL_AndroidMediaCodecFileFrame : public PipeLineElem
{
public:
    PL_AndroidMediaCodecFileFrame();
    virtual ~PL_AndroidMediaCodecFileFrame();
    virtual bool init(void* args);
    virtual void finit();
    virtual bool pay(const PipeMaterial& pm);
    virtual bool gain(PipeMaterial& pm);
private:
    void* internal;
    bool  m_b_loop_play;
    std::string m_str_context;
    std::string m_str_old_context;
    std::string m_str_buf;
    int m_begin;
    long long m_current_time;
private:
    int write_file(const char*,const char*,int);
    int read_file(const char*);
    int analyse_context();
};
PipeLineElem* create_PL_AndroidMediaCodecFileFrame();
#endif
RtspFace/my_timer.hpp
New file
@@ -0,0 +1,65 @@
/***********************************************************
* Date: 2016-06-30
*
* Author: 牟韵
*
* Email: mouyun1115@163.com
*
* Module: 计时器
*
* Brief:
*
* Note:
*
* CodePage: Pure UTF-8
************************************************************/
#ifndef    __MY_TIMER_HPP_BY_MOUYUN_2014_09_28__
#define    __MY_TIMER_HPP_BY_MOUYUN_2014_09_28__
#include <chrono>
namespace my_module_space
{
    class Timer
    {
    public:
        Timer() : m_begin(std::chrono::high_resolution_clock::now()) {}
        ~Timer() {}
    private:
        Timer(const Timer&) = delete;
        Timer(Timer&&) = delete;
        Timer operator=(const Timer&) = delete;
    public:
        void reset()
        {
            m_begin = std::chrono::high_resolution_clock::now();
        }
        double tell_s() const
        {
            return std::chrono::duration_cast<std::chrono::duration<double> >(std::chrono::high_resolution_clock::now() - m_begin).count();
        }
        long long tell_ms() const
        {
            return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - m_begin).count();
        }
        long long tell_us() const
        {
            return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - m_begin).count();
        }
        long long tell_ns() const
        {
            return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - m_begin).count();
        }
    private:
        std::chrono::time_point<std::chrono::high_resolution_clock> m_begin;
    };
}
#endif