当前位置: 首页 > news >正文

湛江网站建设电话宁波百度推广优化

湛江网站建设电话,宁波百度推广优化,用cs6怎么做网站,女生适合学什么专业在Android平台上合成视频一般使用MediaCodec进行硬编码,使用MediaMuxer进行封装,但是因为MediaMuxer支持格式有限,一般会采用ffmpeg封装,比如监控一般使用mpeg2ts格式而非MP4,这是因为两者对帧时pts等信息封装差异导致应用场景不同…

在Android平台上合成视频一般使用MediaCodec进行硬编码,使用MediaMuxer进行封装,但是因为MediaMuxer支持格式有限,一般会采用ffmpeg封装,比如监控一般使用mpeg2ts格式而非MP4,这是因为两者对帧时pts等信息封装差异导致应用场景不同。

数据流转

相机帧数据输出到编码器mediacodec经过h264编码输出压缩数据 MediaCodec.BufferInfo

经由Mpeg2TsUtils传递给ffmpeg ,ffmpeg初始化AVFormatContext 输出上下文添加视频流

将编码器输出帧重新封装AVPacket 写入输出流。

1.1 编码器输出对接

定义 IFrameMuxer 实现编码输出流封装 ,并定义Mpeg2TsMuxer 实现mpeg2ts格式封装

1  IFrameMuxer

public abstract class IFrameMuxer {protected String filePath;protected int format;protected int orientationHint;public IFrameMuxer(String filePath, int format, int orientationHint) {this.orientationHint = orientationHint;this.filePath = filePath;this.format = format;}.....public abstract void start();public abstract void stop();public abstract void writeSampleData(boolean videoTrack, ByteBuffer outputBuffer, MediaCodec.BufferInfo bufferInfo);public abstract int addTrack(MediaFormat mediaFormatChanged, boolean video);public abstract void config(ByteBuffer configBuffer);
}

2  Mpeg2TsMuxer

package com.tyearlin.camera2;import android.media.MediaCodec;
import android.media.MediaFormat;
import android.util.Log;import java.nio.ByteBuffer;import nl.bravobit.mpeg2ts.Mpeg2TsUtils;public class Mpeg2TsMuxer extends IFrameMuxer {private static final String TAG = "Mpeg2TsMuxer";public volatile boolean running = false;public Mpeg2TsMuxer(String filePath, int format, int orientationHint) {super(filePath, format, orientationHint);Log.i(TAG, "Mpeg2TsMuxer:");Mpeg2TsUtils.init(filePath, 1280, 1024);}@Overridepublic int addTrack(MediaFormat outputFormat, boolean isVideo) {return 0;}@Overridepublic void config(ByteBuffer buffer) {int size = buffer.capacity();Mpeg2TsUtils.config(buffer,size);}@Overridepublic void start() {if (running) {Log.e(TAG, "has on running ");throw new IllegalStateException("Muxer is running should stop first ");}Mpeg2TsUtils.start();running = true;}@Overridepublic void stop() {running = false;Mpeg2TsUtils.stop();}@Overridepublic void writeSampleData(boolean videoTrack, ByteBuffer outputBuffer, MediaCodec.BufferInfo bufferInfo) {if(!running) {Log.e(TAG,"not running");return;}long size = bufferInfo.size;long pts = bufferInfo.presentationTimeUs;boolean keyFrame = (bufferInfo.flags & MediaCodec.BUFFER_FLAG_KEY_FRAME) != 0;Mpeg2TsUtils.write_encoded_frame(outputBuffer, size, pts, keyFrame);}
}

3 对接mediacodec 输出

编码器部分通过注册监听回调 调用Mpeg2TsMuxer 对应方法。

1.2  JNI 方法实现

jni承接上下文

1.2.1初始化 ffmpeg相关上下文

extern "C"
JNIEXPORT jlong JNICALL
Java_nl_bravobit_mpeg2ts_Mpeg2TsUtils_init(JNIEnv *env, jclass clazz, jstring path, jint width,jint height) {av_log_set_callback(av_log_android_print_callback);
//    av_log_test();//创建输出路径const char *file_path = env->GetStringUTFChars(path, JNI_FALSE);H2642Ts *h2642Ts = H2642Ts::instance();h2642Ts->av_init(file_path, width, height);env->ReleaseStringUTFChars(path, file_path);return reinterpret_cast<long>(h2642Ts);}

1.2.2  写入每一帧h264编码数据

mpeg2ts还支持其它格式 android自带 MediaMuxer不支持mpeg2ts ,虽然framwork层已有mpeg2ts write实现但未对sdk开放接口,也可以修改固件支持

extern "C"
JNIEXPORT jint JNICALL
Java_nl_bravobit_mpeg2ts_Mpeg2TsUtils_write_1encoded_1frame(JNIEnv *env, jclass clazz,jobject buffer, jlong size, jlong pts,jboolean is_key_frame) {//封装 h264 流H2642Ts *h2642Ts = H2642Ts::instance();uint8_t *data = static_cast<uint8_t *>(env->GetDirectBufferAddress(buffer));int ret = h2642Ts->write_packet(data, size, pts, is_key_frame);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "write_packet failed ret=  %d", ret);}return ret;
}

1.3 mpeg2ts封装实现

定义H2642Ts.cpp实现整个封装功能 直接通过调用 ffmpeg 实现

//
// Created by Q 2023/7/28.
//#ifndef CAMERA2STREAMGET_H2642TS_H
#define CAMERA2STREAMGET_H2642TS_Hextern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
#include <libavutil/timestamp.h>
}#include <thread>using namespace std;class H2642Ts {public:void init();static H2642Ts *instance();void av_init(const char *path, int width, int height);/*** 写入编码数据帧*/int write_packet(uint8_t *data, long size, long pts, bool isKeyFrame);int write_strem_params(uint8_t *data, int size);void printf_packet(AVFormatContext *fmt_ctx, AVPacket *pkt) ;int stop();int start();void release();private:AVFormatContext *ofmt_ctx;AVStream *out_stream;static H2642Ts *m_pInstance;static std::mutex m_Mutex   ;AVFormatContext *createAvFormatOutContext(const char *path);AVStream *createAvStream(int width, int height);H2642Ts();~H2642Ts();};#endif //CAMERA2STREAMGET_H2642TS_H

1.3.1 创建  createAvFormatOutContext

指定输出文件格式及路径 ffmpeg会根据avformat_alloc_output_context2  传入的format name “mpegts”通过av_guess_format方法遍历

muxer_list 匹配对应的 AVOutputFormat ,


AVFormatContext *H2642Ts::createAvFormatOutContext(const char *path) {AVFormatContext *ofmt_ctx;av_log(nullptr, AV_LOG_INFO,"createAvFormatOutContext: path = %s ",path);int ret = avformat_alloc_output_context2(&ofmt_ctx, nullptr, "mpegts", path);av_log(ofmt_ctx, AV_LOG_INFO,"createAvFormatOutContext: ret = %d ",ret);if (ret < 0) {av_log(nullptr, AV_LOG_ERROR,"avformat_alloc_output_context2: Something went really wrong .\n");return nullptr;}int result = avio_open(&ofmt_ctx->pb, path, AVIO_FLAG_READ_WRITE);if(result < 0) {av_log(ofmt_ctx,AV_LOG_INFO,"SingleAudioRecorder::StartRecord avio_open ret=%d", result);avformat_free_context(ofmt_ctx);return nullptr ;}return ofmt_ctx;
}

1.3.2 添加输出流 

这里 avformat_new_stream创建 并自动添加到AVFormatContext-> streams列表内

AVStream *H2642Ts::createAvStream(int width, int height) {av_log(ofmt_ctx, AV_LOG_INFO,"createAvStream");AVStream *stream = avformat_new_stream(ofmt_ctx, nullptr);if (!stream) {av_log(ofmt_ctx, AV_LOG_ERROR,"Failed allocating output stream .\n");return nullptr;}av_log(ofmt_ctx, AV_LOG_INFO, " stream index = %d .\n", stream->index);AVCodecParameters *codecpar = stream->codecpar;codecpar->codec_type = AVMEDIA_TYPE_VIDEO;codecpar->codec_id = AV_CODEC_ID_H264;codecpar->width = width;codecpar->height = height;return stream;
}

1.3.3 写入头部信息

int H2642Ts::start() {if (!ofmt_ctx) {av_log(nullptr, AV_LOG_ERROR,"ofmt_ctx is null: Something went really wrong .\n");return -1;}av_log(ofmt_ctx, AV_LOG_INFO,"start");
//    AVDictionary *dict;
//    int ret = av_dict_set(&dict, "tsflags", "faststart", 0);
//    if (ret < 0) {
//        av_log(ofmt_ctx, AV_LOG_ERROR,
//               "av_dict_set ret = %d : Something went really wrong .\n", ret);
//        return ret;
//    }if (!ofmt_ctx->streams || !out_stream) {av_log(ofmt_ctx, AV_LOG_ERROR,"ofmt_ctx->streams not ready : Something went really wrong .\n");return -1;}return avformat_write_header(ofmt_ctx, nullptr);
}

1.3.4 配置输出流参数(主要sps/pps)

int H2642Ts::write_strem_params(uint8_t *data, int size) {if (!out_stream) {av_log(ofmt_ctx, AV_LOG_ERROR,"out_stream is null");return -1;}AVCodecParameters *codecpar = out_stream->codecpar;if (codecpar == nullptr) {av_log(ofmt_ctx, AV_LOG_INFO, "codecpar is null");return -1;}codecpar->extradata = (uint8_t *) av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE);
//    codecpar->extradata = (uint8_t *) av_mallocz(size );memcpy(codecpar->extradata, data, size);codecpar->extradata_size = size;return 0;
}

注意 padding_size

/*** Extra binary data needed for initializing the decoder, codec-dependent.** Must be allocated with av_malloc() and will be freed by* avcodec_parameters_free(). The allocated size of extradata must be at* least extradata_size + AV_INPUT_BUFFER_PADDING_SIZE, with the padding* bytes zeroed.*/
uint8_t *extradata;

1.3.5 写入编码帧

注意时间基转换  

int H2642Ts::write_packet(uint8_t *data, long size, long pts, bool isKeyFrame) {// 获取视频编码数据地址av_log(ofmt_ctx, AV_LOG_INFO,"call write_packet:size:%d", size);AVPacket *packet = av_packet_alloc();av_init_packet(packet);packet->stream_index = out_stream->index;packet->data = data;packet->size = size;packet->pts = av_rescale_q(pts, {1, 1000000}, out_stream->time_base);packet->dts = packet->pts;
//    packet->duration =packet->flags |= isKeyFrame ? AV_PKT_FLAG_KEY : 0;av_log(ofmt_ctx, AV_LOG_INFO,"write_packet: start");int ret = av_interleaved_write_frame(ofmt_ctx, packet);printf_packet(ofmt_ctx,packet);av_packet_unref(packet);av_packet_free(&packet);av_log(ofmt_ctx, AV_LOG_INFO,"write_packet: end");return ret;}

 对于频繁处理的对象可以创建全局变量动态更换属性 而不是每次都创建 

1.3.6 结束写入尾部信息

int H2642Ts::stop() {if (!ofmt_ctx) {av_log(nullptr, AV_LOG_ERROR,"ofmt_ctx is null: Something went really wrong .\n");return -1;}av_log(ofmt_ctx, AV_LOG_INFO,"stop");av_write_trailer(ofmt_ctx);avio_closep(&ofmt_ctx->pb);avformat_free_context(ofmt_ctx);return 0;
}


文章转载自:
http://economization.cwgn.cn
http://warthog.cwgn.cn
http://scutcher.cwgn.cn
http://ag.cwgn.cn
http://shadberry.cwgn.cn
http://greenhorn.cwgn.cn
http://scourge.cwgn.cn
http://biocellate.cwgn.cn
http://detruncation.cwgn.cn
http://wastelot.cwgn.cn
http://unblamed.cwgn.cn
http://firearm.cwgn.cn
http://episcopalism.cwgn.cn
http://payday.cwgn.cn
http://jaup.cwgn.cn
http://megass.cwgn.cn
http://incused.cwgn.cn
http://payee.cwgn.cn
http://superaqueous.cwgn.cn
http://pelota.cwgn.cn
http://overstability.cwgn.cn
http://disbranch.cwgn.cn
http://agnathous.cwgn.cn
http://semidome.cwgn.cn
http://anilin.cwgn.cn
http://arabist.cwgn.cn
http://crimped.cwgn.cn
http://cachinnatoria.cwgn.cn
http://congenerous.cwgn.cn
http://secern.cwgn.cn
http://nederland.cwgn.cn
http://conquistador.cwgn.cn
http://supererogation.cwgn.cn
http://neaten.cwgn.cn
http://testament.cwgn.cn
http://micron.cwgn.cn
http://cipherkey.cwgn.cn
http://oniongrass.cwgn.cn
http://inseverably.cwgn.cn
http://conchoid.cwgn.cn
http://palship.cwgn.cn
http://puntabout.cwgn.cn
http://gangsterism.cwgn.cn
http://astroid.cwgn.cn
http://ileostomy.cwgn.cn
http://cruse.cwgn.cn
http://isadora.cwgn.cn
http://agamogenetic.cwgn.cn
http://sortita.cwgn.cn
http://prepositional.cwgn.cn
http://mensural.cwgn.cn
http://cineole.cwgn.cn
http://sucrose.cwgn.cn
http://lightly.cwgn.cn
http://monadnock.cwgn.cn
http://buonaparte.cwgn.cn
http://nematocidal.cwgn.cn
http://rabbanite.cwgn.cn
http://millstone.cwgn.cn
http://anaphase.cwgn.cn
http://arcaded.cwgn.cn
http://serotherapy.cwgn.cn
http://lampshade.cwgn.cn
http://loading.cwgn.cn
http://fress.cwgn.cn
http://bemazed.cwgn.cn
http://basketball.cwgn.cn
http://numerously.cwgn.cn
http://incommensurate.cwgn.cn
http://criticastry.cwgn.cn
http://general.cwgn.cn
http://preaseptic.cwgn.cn
http://vehemently.cwgn.cn
http://laminose.cwgn.cn
http://morphallaxis.cwgn.cn
http://shintoist.cwgn.cn
http://sobby.cwgn.cn
http://succumb.cwgn.cn
http://rumply.cwgn.cn
http://spreathed.cwgn.cn
http://mensural.cwgn.cn
http://kuybyshev.cwgn.cn
http://burl.cwgn.cn
http://filmmaker.cwgn.cn
http://alabaman.cwgn.cn
http://megalocephalous.cwgn.cn
http://turnipy.cwgn.cn
http://ostleress.cwgn.cn
http://papilloedema.cwgn.cn
http://subparallel.cwgn.cn
http://wantless.cwgn.cn
http://epizoite.cwgn.cn
http://insemination.cwgn.cn
http://sarcocarp.cwgn.cn
http://humidifier.cwgn.cn
http://exordial.cwgn.cn
http://marxian.cwgn.cn
http://remorseful.cwgn.cn
http://recall.cwgn.cn
http://bookmaker.cwgn.cn
http://www.hrbkazy.com/news/94236.html

相关文章:

  • 如何开发电子商务网站企业网站seo多少钱
  • 在哪个网站做网上兼职靠谱成都高端品牌网站建设
  • 怎么看网站是否织梦快推达seo
  • 网站被挂黑链怎么删除网站展示型推广
  • 网站首页设计分析电销系统软件排名
  • wordpress 做大网站女教师遭网课入侵视频大全集
  • 注册东莞的公司可以买深圳社保吗肇庆网站快速排名优化
  • 给wordpress添加引导页长沙seo霜天
  • wordpress只显示标题2022年百度seo
  • 网站建设企业建站营销策划公司名称
  • 比较大的做网站的公司做网站平台需要多少钱
  • 网站策划师有前途吗教育培训网
  • wordpress建博客网站吗免费b2b平台推广
  • 米特号类似网站seo网站编辑是做什么的
  • 网站开发 chrome gimp搜索引擎推广方案
  • 专门做图表的网站长春最新发布信息
  • 旅游网站建设主要工作怎么样免费做网站
  • 南通企业网站建设公司沈阳关键词推广
  • 门户网站方案刷粉网站推广马上刷
  • 张家港企业网站设计郑州seo哪家好
  • 网站后台 模板seo推广官网
  • 网站头部固定广州百度关键词搜索
  • 服务器租用价格汕头网站优化
  • 华秋商城北京优化seo公司
  • 杭州专业网站设计搜盘 资源网
  • 做网站优化有用吗网站推广平台
  • 龙海网站建设哪家好seo关键词推广
  • 免费开网店平台有哪些seo搜索引擎优化培训班
  • 广州有哪些做网站的公司地推平台
  • 网站被k怎么恢复网页设计与制作书籍