用ffmpeg提取mp4的h264碼流寫檔案花屏
1、用ffmpeg提取mp4的h264碼流寫檔案的方法網上有很多,不知道的請參考雷神部落格:http://blog.csdn.net/leixiaohua1020/article/details/11800877
2、但是這麼寫出來的檔案是有問題的,首先的確能播放,但是會有很大機率出現花屏
a、首先說說解決方案
其實很簡單,也是利用av_bitstream_filter_filter方法把每個AVPacket處理下,如下:
b、再說說原因AVPacket tempPack; av_copy_packet(&tempPack, &pkt_in); av_bitstream_filter_filter(bsfc, pCodecCtx, NULL, &tempPack.data, &tempPack.size, tempPack.data, tempPack.size, 0); fwrite(tempPack.data,pkt_in.size,1,fp_filter);
在ffmpeg中,一個AVPacket中有可能包含不止一個nal,所以按雷神那麼處理的話,同一個AVPacket中的第二個nal就沒有新增其實標誌00 00 00 01,如果剛好這個nal是其他nal參考的話,那麼就會出現花屏。
c、在說說AVPacket.data中nal是如何儲存的
在AVPacket.data中每個nal沒有起始碼00 00 00 01,其中nal的結構是起始4位元組的nal資料長度(不包括這4位元組),然後才是真正的nal資料。
如下圖:
貼下示例程式碼:
/* *寫Nal測試 * *繆國凱 Mickel *[email protected] * *本程式實現了讀取H264編碼視訊儲存為nal檔案,其中有2種寫法,第一種就是網上常見的在每個AVPacket的data前加nal頭 *第二種是用filter,此程式把每一個AVPacket都單獨寫成了一個nal,可以做每一幀的nal檔案對比,如果想把所有幀 *寫成h264碼流檔案,自己改造程式不每幀新開個檔案就好了。 */ #include "stdafx.h" #ifdef __cplusplus extern "C" { #endif #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #pragma comment(lib, "avcodec.lib") #pragma comment(lib, "avformat.lib") #pragma comment(lib, "avutil.lib") #ifdef __cplusplus }; #endif #include <vector> #include <string> AVFormatContext *ifmt_ctx = NULL; #include <stdio.h> int g_videoIndex = -1; int openinputfile(const char* filename) { int ret = 0; //open the input if ((ret = avformat_open_input(&ifmt_ctx, filename, NULL, NULL)) < 0) { printf("can not open input"); return ret; } if ((ret = avformat_find_stream_info(ifmt_ctx, NULL))) { printf("can not find input stream info"); return ret; } //open the decoder for (int i = 0; i < ifmt_ctx->nb_streams; i++) { if (ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { g_videoIndex = i; ret = avcodec_open2(ifmt_ctx->streams[i]->codec, avcodec_find_decoder(ifmt_ctx->streams[i]->codec->codec_id), NULL); if (ret < 0) { printf("can not open decoder"); return ret; } } } return 0; } int _tmain(int argc, _TCHAR* argv[]) { if (argc < 2) { return -1; } AVPacket pkt_in, pkt_out; AVFrame *frame = NULL; unsigned int stream_index; av_register_all(); if (openinputfile(argv[1]) < 0) { printf("failed to open input file"); goto end; } if (g_videoIndex == -1) { return -1; } FILE *fp_sps=fopen("testNal/testNal/sps.h264","wb+"); FILE *fp_f_sps=fopen("testNal/testFilterNal/sps.h264","wb+"); FILE *testMaFp = fopen("testMaual.h264","wb+"); AVCodecContext *pCodecCtx= ifmt_ctx->streams[g_videoIndex]->codec; unsigned char *dummy=NULL; //輸入的指標 int dummy_len; fwrite(pCodecCtx->extradata,pCodecCtx->extradata_size,1,fp_sps); AVBitStreamFilterContext* bsfc = av_bitstream_filter_init("h264_mp4toannexb"); av_bitstream_filter_filter(bsfc, pCodecCtx, NULL, &dummy, &dummy_len, NULL, 0, 0); fwrite(pCodecCtx->extradata,pCodecCtx->extradata_size,1,fp_f_sps); fclose(fp_sps); fclose(fp_f_sps); fwrite(pCodecCtx->extradata,pCodecCtx->extradata_size,1,testMaFp); int totol_frame_index = 0; while(1) { if (av_read_frame(ifmt_ctx, &pkt_in) < 0) { break; } if (ifmt_ctx->streams[pkt_in.stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { //第一種寫法,在每個frame前加nal頭 char tmpName[100]; sprintf(tmpName, "testNal/testNal/frame_%d.h264", totol_frame_index); FILE *fp=fopen(tmpName,"wb+"); if (fp) { char nal_start[]={0,0,0,1}; fwrite(nal_start,4,1,fp); fwrite(pkt_in.data+4,pkt_in.size-4,1,fp); fclose(fp); } //第二種寫法,用av_bitstream_filter_filter sprintf(tmpName, "testNal/testFilterNal/frame_%d.h264", totol_frame_index); FILE *fp_filter=fopen(tmpName,"wb+"); if (fp_filter) { AVPacket tempPack; av_copy_packet(&tempPack, &pkt_in); av_bitstream_filter_filter(bsfc, pCodecCtx, NULL, &tempPack.data, &tempPack.size, tempPack.data, tempPack.size, 0); fwrite(tempPack.data,pkt_in.size,1,fp_filter); fclose(fp_filter); } totol_frame_index++; } continue; } av_bitstream_filter_close(bsfc); free(dummy); fclose(testMaFp); end: avformat_close_input(&ifmt_ctx); getchar(); return 0; }
相關推薦
用ffmpeg提取mp4的h264碼流寫檔案花屏
1、用ffmpeg提取mp4的h264碼流寫檔案的方法網上有很多,不知道的請參考雷神部落格:http://blog.csdn.net/leixiaohua1020/article/details/11800877 2、但是這麼寫出來的檔案是有問題的,首先的確能播放,但是會有
java調用ffmpeg命令行推流遇到的問題
處理 buffere process 占用 調用 .exe 緩沖池 rst proc 1.Java調用命令行,如果沒有額外環境變量,不指定工作路徑,Runtime有兩個方法 public Process exec(String command) public Proces
使用IO流寫檔案的一些騷操作
序言 當需要對檔案進行操作時,使用IO流是不能避免的操作;比如業務中需要儲存一些請求的響應結果中的一些內容。當所需處理的檔案過大時,如果頻繁的關閉檔案流,會造成很大的開銷,何時關閉?往往會造成比較大的困擾。那麼如何才能比較優雅的處理檔案呢? 使用案例 情景 儲存資料時,行與行之間使用回車符隔開;一行的
Java利用JNI呼叫FFMpeg對h264碼流進行解碼
前期配置工作: 使用JNI呼叫: java端: package com.recon.action; public class Decode { public native String loadfile(String s); //
關於JAVA IO流寫檔案數字亂碼的問題
在完成JavaWeb作業時遇到一題是需要持久化儲存登入人數的,題主當時就在Listener裡寫了輸入輸出兩個函式,但是檢查一看發現寫入的數字變成了亂碼(其實不能說是亂碼)。 當時很疑惑就改用瞭如下程式碼: 寫程式碼: File file = new File(PATH);
調用FFmpeg SDK對H.264格式的視頻壓縮碼流進行解碼
b- follow 分享圖片 vpd fff proc ofo com 進行 由於作者不習慣該編輯器,只是將本文的截圖貼了出來,詳文見:https://www.yuque.com/docs/share/cce69b1b-b619-44b5-acd1-efa229d8862
使用FFMPEG類庫分離出多媒體檔案中的H 264碼流
在使用FFMPEG的類庫進行程式設計的過程中,可以直接輸出解複用之後的的視訊資料碼流。只需要在每次呼叫av_read_frame()之後將得到的視訊的AVPacket存為本地檔案即可。經試驗,在分離MPEG2碼流的時候,直接儲存AVPacket即可。在分離H.264碼流的時候,
在MP4檔案中提取H264的SPS、PPS及碼流
一、MP4封裝格式的基本概念 1 MP4封裝格式對應標準為 ISO/IEC 14496-12(資訊科技 視聽物件編碼的第12部分: ISO 基本媒體檔案格式/Information technology Coding of audio-visual objects Pa
java中使用檔案輸入流和檔案輸出流進行檔案讀寫的用例!
package com.cfkyit.io; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutp
用java寫檔案輸入輸出流,實現複製貼上的方法
java中檔案輸入輸出流是FileInputStream和FileOutputStream,檔案輸入流從檔案系統中的某個檔案中獲得輸入位元組,然後可以用輸出流將資料寫入檔案中。 首先建立兩個流的物件: FileInputStream的構造方法有三種過載方式,常用的是F
FFmpeg總結(十二)用ffmpeg與nginx實現直播多路流並發播放
xxx 開源 conf ref itl rect arc med rtm 圖:撒哈拉沙漠 下載 nginx 和 nginx-rtmp源碼: http://nginx.org/download/nginx-1.5.10.tar.gz https://github.com/a
反-反爬蟲:用幾行代碼寫出和人類一樣的動態爬蟲
簽名 lib rgs 常見 todo 只需要 website 結束 pro 歡迎大家前往騰訊雲技術社區,獲取更多騰訊海量技術實踐幹貨哦~ 作者:李大偉 Phantomjs簡介 什麽是Phantomjs Phantomjs官網介紹是:不需要瀏覽器的完整web協議棧(Fu
寫網站經常需要用到的代碼匯總
log false setfont 初始 設置 chrome 布局 兼容 name 常用視口 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0
java壓縮文件解壓:調用WinRAR5命令強於自己寫代碼實現
成功 cat val value util sub 屬性 eal mon 最近,手上維護著一個幾年前的系統,技術是用的JSP+Strust2,系統提供了rar和zip兩種壓縮格式的解壓功能,後臺是用java實現的 1、解壓rar格式,采用的是java-unrar-0.3.j
147_IO_節點流_位元組流_檔案讀取_寫出_追加檔案
檔案的讀取 Test01_InputStream.java package _02.io.byteStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNot
PS流解複用成H264和音訊流(ES提取)
技術在於交流、溝通,轉載請註明出處並保持作品的完整性。 原文:https://blog.csdn.net/hiwubihe/article/details/80759142 [本系列相關文章] H264和音訊流打包成PS流 (MPEG2-PS
FFmpeg入門--碼流 / 位元速率 / 位元率 / 幀速率 / 解析度 【1】
I、P、B 幀 I 幀(Intracoded frames):I 幀影象採用幀內編碼方式,即只利用了單幀影象內的空間相關性,而沒有利用時間相關性。I 幀使用幀內壓縮,不使用運動補償,由於I 幀不依賴其它幀,所以是隨機存取的入點,同時是解碼的基準幀。I 幀主要用於接收機的初始化和通
FFmpeg In Android - H264碼流解碼/OpenGL ES渲染
主要思路是FFmpeg解碼H264得到一張yuv420p圖片後,傳遞給opengl es在著色器內部做圖片轉換yuv->rgb,然後通過紋理貼圖的方式渲染出來.這種方式的效率更高.核心程式碼如下: #include "common.h" #include "gl_util.h"
FFmpeg In Android - H264碼流解碼/儲存Yuv
本節例子原始碼_NativeH264Android,修改自ffmpeg原始碼目錄/doc/examples/decode_video.c H264的碼流結構 H.264原始碼流(又稱為“裸流”)是由一個一個的NALU組成的,包括I幀,B幀,P幀等等,他們的結構如下圖所示: 其中每個
C++利用一個fstream流讀寫檔案
原文地址:https://blog.csdn.net/qq_34176290/article/details/80260377 fstream物件可以同時具有ifstream和ofstream的功能,嘗試使用一個流對檔案進行讀寫的程式碼如下: