lguess 长款女士钱包价格,swsport女士钱包

  

  在项目中经常需要进行视频解码、编码和封装等操作,本文主要阐述“YUV编码为H264 "和“H264封装为MP4 "两个过程。   

  

  1 YUV编码为H264YUV编码为H264有两种方式:   

  

  (1)基于工具调用libx264实现YUV420P的像素数据编码为264的压缩编码数据;   

  

  (2)直接调用libx264将输入的YUV数据编码为264码流文件;1.1 基于FFmpeg YUV编码为H264   

  

  使用FFmpeg编码视频涉及的主要函数:   

  

  av_register_all():注册FFmpeg所有编解码器。   

  

  avformat_alloc_output_context2():初始化输出码流的AVFormatContext。   

  

  avio_open():打开输出文件。   

  

  av_new_stream().创建输出码流的音频流。   

  

  音像的编解码器_查找_编码器():查找编码器。   

  

  avcodec_open2():打开编码器。   

  

  avformat_write_header():写文件头(对于某些没有文件头的封装格式,不需要此函数。比如说MPEG2TS)。   

  

  音像的编解码器_编码_视频2():编码一帧视频。即将AVFrame(存储YUV像素数据)编码为AVPacket(存储264等格式的码流数据)。   

  

  av_write_frame():将编码后的视频码流写入文件。   

  

  同花顺_编码器():输入的像素数据读取完成后调用此函数。用于输出编码器中剩余的AVPacket。   

  

  av_write_trailer().写文件尾(对于某些没有文件头的封装格式,不需要此函数。比如说MPEG2TS)。   

  

  代码:   

  

  #包含stdio。h #定义_ _ STDC _常量_宏# ifdef _ WIN32//windows extern ' C ' { # include ' libavutil/opt。h ' # include ' libavcodec/avcodec。h ' # include ' libavformat/av格式。h ' };#else//Linux.# ifdef _ _ cplusplusextern ' C ' { # endif # include libavutil/opt。h #包括libavcodec/avcodec。h #包括libavformat/av格式。h # ifdef _ _ cplusplus };# endif #迪恩fint flush _ encoder(AVFormatContext * fmt _ CTX,unsigned int stream _ index){ int ret;int got _ frameAVPacket enc _ pkt如果(!(fmt _ CTX-流-编解码器-编解码器-功能编解码器_上限_延迟))返回0;while(1){ enc _ PKT。数据=空;enc _ PKT。大小=0;av _ init数据包(enc _ PKT);ret=av codec _ encode _ video 2(fmt _ CTX-流-编解码器,enc_pkt,NULL,got _ frame);av _帧_自由(空);if (ret 0)中断;如果(!got _ frame){ ret=0;打破;} printf('Flush编码器:成功编码一帧!\tsize:]\n ',enc _ PKT。尺寸);/*多路复用编码帧*/ret=av_write_frame(fmt_ctx,enc _ PKT);if (ret 0)中断;浸水使柔软返回;}int main(int argc,char * argv){ AVFormatContext * pformatcx;AVOutputFormat * fmtAVStream * video _ stAVCodecContext * pcodecctxavcode * pcodecafpacket pktuint 8 _ t * picture _ bufavrament * p frame(同国际组织)国际组织   

picture_size; int y_size; int framecnt=0; //FILE *in_file = fopen("src01_480x272.yuv", "rb"); //Input raw YUV data FILE *in_file = fopen("../ds_480x272.yuv", "rb"); //Input raw YUV data int in_w=480,in_h=272; //Input data's width and height int framenum=100; //Frames to encode //const char* out_file = "src01.h264"; //Output Filepath //const char* out_file = "src01.ts"; //const char* out_file = "src01.hevc"; const char* out_file = "ds.h264"; av_register_all(); //Method1. pFormatCtx = avformat_alloc_context(); //Guess Format fmt = av_guess_format(NULL, out_file, NULL); pFormatCtx->oformat = fmt; //Method 2. //avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, out_file); //fmt = pFormatCtx->oformat; //Open output URL if (avio_open(&pFormatCtx->pb,out_file, AVIO_FLAG_READ_WRITE) < 0){ printf("Failed to open output file! \n"); return -1; } video_st = avformat_new_stream(pFormatCtx, 0); video_st->time_base.num = 1; video_st->time_base.den = 25; if (video_st==NULL){ return -1; } //Param that must set pCodecCtx = video_st->codec; //pCodecCtx->codec_id =AV_CODEC_ID_HEVC; pCodecCtx->codec_id = fmt->video_codec; pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO; pCodecCtx->pix_fmt = PIX_FMT_YUV420P; pCodecCtx->width = in_w; pCodecCtx->height = in_h; pCodecCtx->time_base.num = 1; pCodecCtx->time_base.den = 25; pCodecCtx->bit_rate = 400000; pCodecCtx->gop_size=250; //H264 //pCodecCtx->me_range = 16; //pCodecCtx->max_qdiff = 4; //pCodecCtx->qcompress = 0.6; pCodecCtx->qmin = 10; pCodecCtx->qmax = 51; //Optional Param pCodecCtx->max_b_frames=3; // Set Option AVDictionary *param = 0; //H.264 if(pCodecCtx->codec_id == AV_CODEC_ID_H264) { av_dict_set(m, "preset", "slow", 0); av_dict_set(m, "tune", "zerolatency", 0); //av_dict_set(m, "profile", "main", 0); } //H.265 if(pCodecCtx->codec_id == AV_CODEC_ID_H265){ av_dict_set(m, "preset", "ultrafast", 0); av_dict_set(m, "tune", "zero-latency", 0); } //Show some Information av_dump_format(pFormatCtx, 0, out_file, 1); pCodec = avcodec_find_encoder(pCodecCtx->codec_id); if (!pCodec){ printf("Can not find encoder! \n"); return -1; } if (avcodec_open2(pCodecCtx, pCodec,m) < 0){ printf("Failed to open encoder! \n"); return -1; } pFrame = av_frame_alloc(); picture_size = avpicture_get_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height); picture_buf = (uint8_t *)av_malloc(picture_size); avpicture_fill((AVPicture *)pFrame, picture_buf, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height); //Write File Header avformat_write_header(pFormatCtx,NULL); av_new_packet(&pkt,picture_size); y_size = pCodecCtx->width * pCodecCtx->height; for (int i=0; i<framenum; i++){ //Read raw YUV data if (fread(picture_buf, 1, y_size*3/2, in_file) <= 0){ printf("Failed to read raw data! \n"); return -1; }else if(feof(in_file)){ break; } pFrame->data<0> = picture_buf; // Y pFrame->data<1> = picture_buf+ y_size; // U pFrame->data<2> = picture_buf+ y_size*5/4; // V //PTS pFrame->pts=i; int got_picture=0; //Encode int ret = avcodec_encode_video2(pCodecCtx, &pkt,pFrame, &got_picture); if(ret < 0){ printf("Failed to encode! \n"); return -1; } if (got_picture==1){ printf("Succeed to encode frame: %5d\tsize:%5d\n",framecnt,pkt.size); framecnt++; pkt.stream_index = video_st->index; ret = av_write_frame(pFormatCtx, &pkt); av_free_packet(&pkt); } } //Flush Encoder int ret = flush_encoder(pFormatCtx,0); if (ret < 0) { printf("Flushing encoder failed\n"); return -1; } //Write file trailer av_write_trailer(pFormatCtx); //Clean if (video_st){ avcodec_close(video_st->codec); av_free(pFrame); av_free(picture_buf); } avio_close(pFormatCtx->pb); avformat_free_context(pFormatCtx); fclose(in_file); return 0;}1.2 直接调用libx264 YUV编码为H264
调用libx264进行视频编码涉及的主要函数:
x264_param_default():设置参数集结构体x264_param_t的缺省值。
x264_picture_alloc():为图像结构体x264_picture_t分配内存。
x264_encoder_open():打开编码器。
x264_encoder_encode():编码一帧图像。
x264_encoder_close():关闭编码器。
x264_picture_clean():释放x264_picture_alloc()申请的资源。

  

存储数据的结构体如下所示。
x264_picture_t:存储压缩编码前的像素数据。
x264_nal_t:存储压缩编码后的码流数据。

  

代码:

  

#include <stdio.h> #include <stdlib.h> #include "stdint.h" #if defined ( __cplusplus) extern "C" { #include "x264.h" }; #else #include "x264.h" #endif int main(int argc, char** argv) { int ret; int y_size; int i,j; //FILE* fp_src = fopen("../cuc_ieschool_640x360_yuv444p.yuv", "rb"); FILE* fp_src = fopen("../cuc_ieschool_640x360_yuv420p.yuv", "rb"); FILE* fp_dst = fopen("cuc_ieschool.h264", "wb"); //Encode 50 frame //if set 0, encode all frame int frame_num=50; int csp=X264_CSP_I420; int width=640,height=360; int iNal = 0; x264_nal_t* pNals = NULL; x264_t* pHandle = NULL; x264_picture_t* pPic_in = (x264_picture_t*)malloc(sizeof(x264_picture_t)); x264_picture_t* pPic_out = (x264_picture_t*)malloc(sizeof(x264_picture_t)); x264_param_t* pParam = (x264_param_t*)malloc(sizeof(x264_param_t)); //Check if(fp_src==NULL||fp_dst==NULL){ printf("Error open files.\n"); return -1; } x264_param_default(pParam); pParam->i_width = width; pParam->i_height = height; /* //Param pParam->i_log_level = X264_LOG_DEBUG; pParam->i_threads = X264_SYNC_LOOKAHEAD_AUTO; pParam->i_frame_total = 0; pParam->i_keyint_max = 10; pParam->i_bframe = 5; pParam->b_open_gop = 0; pParam->i_bframe_pyramid = 0; pParam->rc.i_qp_constant=0; pParam->rc.i_qp_max=0; pParam->rc.i_qp_min=0; pParam->i_bframe_adaptive = X264_B_ADAPT_TRELLIS; pParam->i_fps_den = 1; pParam->i_fps_num = 25; pParam->i_timebase_den = pParam->i_fps_num; pParam->i_timebase_num = pParam->i_fps_den; */ pParam->i_csp=csp; x264_param_apply_profile(pParam, x264_profile_names<5>); pHandle = x264_encoder_open(pParam); x264_picture_init(pPic_out); x264_picture_alloc(pPic_in, csp, pParam->i_width, pParam->i_height); //ret = x264_encoder_headers(pHandle, &pNals, &iNal); y_size = pParam->i_width * pParam->i_height; //detect frame number if(frame_num==0){ fseek(fp_src,0,SEEK_END); switch(csp){ case X264_CSP_I444:frame_num=ftell(fp_src)/(y_size*3);break; case X264_CSP_I420:frame_num=ftell(fp_src)/(y_size*3/2);break; default:printf("Colorspace Not Support.\n");return -1; } fseek(fp_src,0,SEEK_SET); } //Loop to Encode for( i=0;i<frame_num;i++){ switch(csp){ case X264_CSP_I444:{ fread(pPic_in->img.plane<0>,y_size,1,fp_src); //Y fread(pPic_in->img.plane<1>,y_size,1,fp_src); //U fread(pPic_in->img.plane<2>,y_size,1,fp_src); //V break;} case X264_CSP_I420:{ fread(pPic_in->img.plane<0>,y_size,1,fp_src); //Y fread(pPic_in->img.plane<1>,y_size/4,1,fp_src); //U fread(pPic_in->img.plane<2>,y_size/4,1,fp_src); //V break;} default:{ printf("Colorspace Not Support.\n"); return -1;} } pPic_in->i_pts = i; ret = x264_encoder_encode(pHandle, &pNals, &iNal, pPic_in, pPic_out); if (ret< 0){ printf("Error.\n"); return -1; } printf("Succeed encode frame: %5d\n",i); for ( j = 0; j < iNal; ++j){ fwrite(pNals.p_payload, 1, pNals.i_payload, fp_dst); } } i=0; //flush encoder while(1){ ret = x264_encoder_encode(pHandle, &pNals, &iNal, NULL, pPic_out); if(ret==0){ break; } printf("Flush 1 frame.\n"); for (j = 0; j < iNal; ++j){ fwrite(pNals.p_payload, 1, pNals.i_payload, fp_dst); } i++; } x264_picture_clean(pPic_in); x264_encoder_close(pHandle); pHandle = NULL; free(pPic_in); free(pPic_out); free(pParam); fclose(fp_src); fclose(fp_dst); return 0; } 2 H264封装为MP4H264封装为MP4有两种方式:
(1)基于FFmpeg使用mp4封装格式封装视频数据;(这种方式效率较低)
(2)根据MP4文件协议直接将H264包封装成MP4格式,通过Mp4v2可以很方便地将H264编码成MP4格式文件
2.1 基于FFmpeg H264封装为MP4
详细的解释参考:https://blog.csdn.net/cfqcfqcfqcfqcfq/article/details/68496213
代码:

  

#include <iostream>extern "C"{#include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libavutil/avutil.h> #include <libswscale/swscale.h> }using namespace std;#pragma comment(lib, "avcodec.lib")#pragma comment(lib, "avformat.lib")#pragma comment(lib, "avutil.lib")#pragma comment(lib, "avdevice.lib")#pragma comment(lib, "avfilter.lib")#pragma comment(lib, "postproc.lib")#pragma comment(lib, "swresample.lib")#pragma comment(lib, "swscale.lib")int flush_encoder(AVFormatContext *fmt_ctx, unsigned int stream_index);int main(int argc, char *argv<>){ AVFormatContext *pFormatCtx = nullptr; AVOutputFormat *fmt = nullptr; AVStream *video_st = nullptr; AVCodecContext *pCodecCtx = nullptr; AVCodec *pCodec = nullptr; uint8_t *picture_buf = nullptr; AVFrame *picture = nullptr; int size; //打开视频 FILE *in_file = fopen("test.yuv", "rb"); if (!in_file) { cout << "can not open file!" << endl; return -1; } int in_w = 1280, in_h = 720; int framenum = 500; const char* out_file = "src01.mp4"; //<1> --注册所有ffmpeg组件 avcodec_register_all(); av_register_all(); //<1> //<2> --初始化AVFormatContext结构体,根据文件名获取到合适的封装格式 avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, out_file); fmt = pFormatCtx->oformat; //<2> //<3> --打开文件 if (avio_open(&pFormatCtx->pb, out_file, AVIO_FLAG_READ_WRITE)) { cout << "output file open fail!"; goto end; } //<3> //<4> --初始化视频码流 video_st = avformat_new_stream(pFormatCtx, 0); if (video_st == NULL) { printf("failed allocating output stram\n"); goto end; } video_st->time_base.num = 1; video_st->time_base.den = 30; //<4> //<5> --编码器Context设置参数 pCodecCtx = video_st->codec; pCodecCtx->codec_id = fmt->video_codec; pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO; pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P; pCodecCtx->width = in_w; pCodecCtx->height = in_h; pCodecCtx->time_base.num = 1; pCodecCtx->time_base.den = 30; pCodecCtx->bit_rate = 6126000; pCodecCtx->gop_size = 12; if (pCodecCtx->codec_id == AV_CODEC_ID_H264) { pCodecCtx->refs = 3; pCodecCtx->qmin = 10; pCodecCtx->qmax = 51; pCodecCtx->qcompress = 0.6; } if (pCodecCtx->codec_id == AV_CODEC_ID_MPEG2VIDEO) pCodecCtx->max_b_frames = 2; if (pCodecCtx->codec_id == AV_CODEC_ID_MPEG1VIDEO) pCodecCtx->mb_decision = 2; //<5> //<6> --寻找编码器并打开编码器 pCodec = avcodec_find_encoder(pCodecCtx->codec_id); if (!pCodec) { cout << "no right encoder!" << endl; goto end; } if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { cout << "open encoder fail!" << endl; goto end; } //<6> //输出格式信息 av_dump_format(pFormatCtx, 0, out_file, 1); //初始化帧 picture = av_frame_alloc(); picture->width = pCodecCtx->width; picture->height = pCodecCtx->height; picture->format = pCodecCtx->pix_fmt; size = avpicture_get_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height); picture_buf = (uint8_t*)av_malloc(size); avpicture_fill((AVPicture*)picture, picture_buf, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height); //<7> --写头文件 avformat_write_header(pFormatCtx, NULL); //<7> AVPacket pkt; //创建已编码帧 int y_size = pCodecCtx->width*pCodecCtx->height; av_new_packet(&pkt, size * 3); //<8> --循环编码每一帧 for (int i = 0; i < framenum; i++) { //读入YUV if (fread(picture_buf, 1, y_size * 3 / 2, in_file) < 0) { cout << "read file fail!" << endl; goto end; } else if (feof(in_file)) break; picture->data<0> = picture_buf; //亮度Y picture->data<1> = picture_buf + y_size; //U picture->data<2> = picture_buf + y_size * 5 / 4; //V //AVFrame PTS picture->pts = i; int got_picture = 0; //编码 int ret = avcodec_encode_video2(pCodecCtx, &pkt, picture, &got_picture); if (ret < 0) { cout << "encoder fail!" << endl; goto end; } if (got_picture == 1) { cout << "encoder success!" << endl; // parpare packet for muxing pkt.stream_index = video_st->index; av_packet_rescale_ts(&pkt, pCodecCtx->time_base, video_st->time_base); pkt.pos = -1; ret = av_interleaved_write_frame(pFormatCtx, &pkt); av_free_packet(&pkt); } } //<8> //<9> --Flush encoder int ret = flush_encoder(pFormatCtx, 0); if (ret < 0) { cout << "flushing encoder failed!" << endl; goto end; } //<9> //<10> --写文件尾 av_write_trailer(pFormatCtx); //<10> end: //释放内存 if (video_st) { avcodec_close(video_st->codec); av_free(picture); av_free(picture_buf); } if (pFormatCtx) { avio_close(pFormatCtx->pb); avformat_free_context(pFormatCtx); } fclose(in_file); return 0;}int flush_encoder(AVFormatContext *fmt_ctx, unsigned int stream_index){ int ret; int got_frame; AVPacket enc_pkt; if (!(fmt_ctx->streams->codec->codec->capabilities & CODEC_CAP_DELAY)) return 0; while (1) { printf("Flushing stream #%u encoder\n", stream_index); enc_pkt.data = NULL; enc_pkt.size = 0; av_init_packet(&enc_pkt); ret = avcodec_encode_video2(fmt_ctx->streams->codec, &enc_pkt, NULL, &got_frame); av_frame_free(NULL); if (ret < 0) break; if (!got_frame) { ret = 0; break; } cout << "success encoder 1 frame" << endl; // parpare packet for muxing enc_pkt.stream_index = stream_index; av_packet_rescale_ts(&enc_pkt, fmt_ctx->streams->codec->time_base, fmt_ctx->streams->time_base); ret = av_interleaved_write_frame(fmt_ctx, &enc_pkt); if (ret < 0) break; } return ret;}2.2通过Mp4v2 H264封装为MP4
说明及代码参考:https://blog.csdn.net/firehood_/article/details/8813587
源码下载地址:https://download.csdn.net/download/davebobo/10403571
如果没有特别说明,YUV编码为H264和H264封装为MP4两个过程均可以基于FFmpeg完成实现。
参考文献:
<1>https://blog.csdn.net/leixiaohua1020/article/details/25430425
<2>http://blog.csdn.net/leixiaohua1020/article/details/42078645
<3>https://blog.csdn.net/cfqcfqcfqcfqcfq/article/details/68496213
<4>http://blog.csdn.net/firehood_/article/details/8813587
<5>http://blog.csdn.net/qq_29350001/article/details/73742075

相关文章