From 5ce6085328a841e270c7ce1ddfdd36efabf0b095 Mon Sep 17 00:00:00 2001
From: xingzilong <xingzilong@454eff88-639b-444f-9e54-f578c98de674>
Date: 星期四, 17 八月 2017 11:46:03 +0800
Subject: [PATCH] h264裸数据读取
---
RtspFace/PL_AndroidMediaCodecFileFrame.cpp | 378 ++++++++++++++++++++++++++++++++++++++++++
RtspFace/PL_AndroidMediaCodecFileFrame.h | 47 +++++
RtspFace/my_timer.hpp | 65 +++++++
3 files changed, 490 insertions(+), 0 deletions(-)
diff --git a/RtspFace/PL_AndroidMediaCodecFileFrame.cpp b/RtspFace/PL_AndroidMediaCodecFileFrame.cpp
new file mode 100644
index 0000000..ed09a1f
--- /dev/null
+++ b/RtspFace/PL_AndroidMediaCodecFileFrame.cpp
@@ -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;
+}
diff --git a/RtspFace/PL_AndroidMediaCodecFileFrame.h b/RtspFace/PL_AndroidMediaCodecFileFrame.h
new file mode 100644
index 0000000..c73f78a
--- /dev/null
+++ b/RtspFace/PL_AndroidMediaCodecFileFrame.h
@@ -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
diff --git a/RtspFace/my_timer.hpp b/RtspFace/my_timer.hpp
new file mode 100644
index 0000000..3241e7d
--- /dev/null
+++ b/RtspFace/my_timer.hpp
@@ -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
--
Gitblit v1.8.0