java中用jave下载 java转换mp4,如果需要转出video标签能识别的h264编码格式,转换的参数应该怎么写?

识别常见编码格式文件并转换成UTF-8编码 的java实现 源码 - Michael.Wang - 博客园
package com.buptsse.ate.
import java.io.BufferedInputS
import java.io.BufferedR
import java.io.F
import java.io.FileInputS
import java.io.FileNotFoundE
import java.io.FileOutputS
import java.io.IOE
import java.io.InputStreamR
import java.io.OutputStreamW
import java.io.UnsupportedEncodingE
import java.io.W
import java.util.ArrayL
import java.util.L
import java.util.regex.M
import java.util.regex.P
* @author michaelw
* @email michael.
public class ConverEncoding {
static String CODE = "UTF-8";
static String FILE_SUFFIX = ".txt";//文件扩展名
// static String FILE_SUFFIX = ".css";
// static String FILE_SUFFIX = ".js";
// static String FILE_SUFFIX = ".htm";
static String srcDir = "C:\\WorkTools\\weenCompany_ChineseEnglish_JT_V5.3.0_UTF8";//文件所在目录
* @param args
* @throws Exception
public static void main(String[] args) throws Exception {
List&String& files = new ArrayList&String&();
fetchFileList(srcDir, files, FILE_SUFFIX);
String filecode = "";
for (String fileName : files) {
filecode = codeString(fileName);
if (!filecode.equals(CODE)) {
convert(fileName, filecode, fileName, CODE);
public static void convert(String oldFile, String oldCharset,
String newFlie, String newCharset) {
FileOutputS
StringBuffer content = new StringBuffer();
System.out.println("the old file is :"+oldFile);
System.out.println("The oldCharset is : "+oldCharset);
bin = new BufferedReader(new InputStreamReader(new FileInputStream(
oldFile), oldCharset));
String line =
while ((line = bin.readLine()) != null) {
// System.out.println("content:" + content);
content.append(line);
content.append(System.getProperty("line.separator"));
bin.close();
File dir = new File(newFlie.substring(0, newFlie.lastIndexOf("\\")));
if (!dir.exists()) {
dir.mkdirs();
fos = new FileOutputStream(newFlie);
Writer out = new OutputStreamWriter(fos, newCharset);
out.write(content.toString());
out.close();
fos.close();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
public static void fetchFileList(String strPath, List&String& filelist,
final String regex) {
File dir = new File(strPath);
File[] files = dir.listFiles();
Pattern p = pile(regex);
if (files == null)
for (int i = 0; i & files. i++) {
if (files[i].isDirectory()) {
fetchFileList(files[i].getAbsolutePath(), filelist, regex);
String strFileName = files[i].getAbsolutePath().toLowerCase();
Matcher m = p.matcher(strFileName);
if (m.find()) {
filelist.add(strFileName);
* 判断文件的编码格式
* @param fileName
* @return 文件编码格式
* @throws Exception
public static String codeString(String fileName) throws Exception {
BufferedInputStream bin = new BufferedInputStream(new FileInputStream(
fileName));
int p = (bin.read() && 8) + bin.read();
String code =
switch (p) {
case 0xefbb:
code = "UTF-8";
case 0xfffe:
code = "Unicode";
case 0xfeff:
code = "UTF-16BE";
code = "GBK";java字符串的各种编码转换 - CSDN博客
java字符串的各种编码转换
import java.io.UnsupportedEncodingE
* 转换字符串的编码
public class ChangeCharset {
/** 7位ASCII字符,也叫作ISO646-US、Unicode字符集的基本拉丁块 */
public static final String US_ASCII = &US-ASCII&;
/** ISO 拉丁字母表 No.1,也叫作 ISO-LATIN-1 */
public static final String ISO_8859_1 = &ISO-8859-1&;
/** 8 位 UCS 转换格式 */
public static final String UTF_8 = &UTF-8&;
/** 16 位 UCS 转换格式,Big Endian(最低地址存放高位字节)字节顺序 */
public static final String UTF_16BE = &UTF-16BE&;
/** 16 位 UCS 转换格式,Little-endian(最高地址存放低位字节)字节顺序 */
public static final String UTF_16LE = &UTF-16LE&;
/** 16 位 UCS 转换格式,字节顺序由可选的字节顺序标记来标识 */
public static final String UTF_16 = &UTF-16&;
/** 中文超大字符集 */
public static final String GBK = &GBK&;
* 将字符编码转换成US-ASCII码
public String toASCII(String str) throws UnsupportedEncodingException{
return this.changeCharset(str, US_ASCII);
* 将字符编码转换成ISO-8859-1码
public String toISO_8859_1(String str) throws UnsupportedEncodingException{
return this.changeCharset(str, ISO_8859_1);
* 将字符编码转换成UTF-8码
public String toUTF_8(String str) throws UnsupportedEncodingException{
return this.changeCharset(str, UTF_8);
* 将字符编码转换成UTF-16BE码
public String toUTF_16BE(String str) throws UnsupportedEncodingException{
return this.changeCharset(str, UTF_16BE);
* 将字符编码转换成UTF-16LE码
public String toUTF_16LE(String str) throws UnsupportedEncodingException{
return this.changeCharset(str, UTF_16LE);
* 将字符编码转换成UTF-16码
public String toUTF_16(String str) throws UnsupportedEncodingException{
return this.changeCharset(str, UTF_16);
* 将字符编码转换成GBK码
public String toGBK(String str) throws UnsupportedEncodingException{
return this.changeCharset(str, GBK);
* 字符串编码转换的实现方法
* @param str
待转换编码的字符串
* @param newCharset 目标编码
* @throws UnsupportedEncodingException
public String changeCharset(String str, String newCharset)
throws UnsupportedEncodingException {
if (str != null) {
//用默认字符编码解码字符串。
byte[] bs = str.getBytes();
//用新的字符编码生成字符串
return new String(bs, newCharset);
* 字符串编码转换的实现方法
* @param str
待转换编码的字符串
* @param oldCharset 原编码
* @param newCharset 目标编码
* @throws UnsupportedEncodingException
public String changeCharset(String str, String oldCharset, String newCharset)
throws UnsupportedEncodingException {
if (str != null) {
//用旧的字符编码解码字符串。解码可能会出现异常。
byte[] bs = str.getBytes(oldCharset);
//用新的字符编码生成字符串
return new String(bs, newCharset);
public static void main(String[] args) throws UnsupportedEncodingException {
ChangeCharset test = new ChangeCharset();
String str = &This is a 中文的 String!&;
System.out.println(&str: & + str);
String gbk = test.toGBK(str);
System.out.println(&转换成GBK码: & + gbk);
System.out.println();
String ascii = test.toASCII(str);
System.out.println(&转换成US-ASCII码: & + ascii);
gbk = test.changeCharset(ascii,ChangeCharset.US_ASCII, ChangeCharset.GBK);
System.out.println(&再把ASCII码的字符串转换成GBK码: & + gbk);
System.out.println();
String iso88591 = test.toISO_8859_1(str);
System.out.println(&转换成ISO-8859-1码: & + iso88591);
gbk = test.changeCharset(iso88591,ChangeCharset.ISO_8859_1, ChangeCharset.GBK);
System.out.println(&再把ISO-8859-1码的字符串转换成GBK码: & + gbk);
System.out.println();
String utf8 = test.toUTF_8(str);
System.out.println(&转换成UTF-8码: & + utf8);
gbk = test.changeCharset(utf8,ChangeCharset.UTF_8, ChangeCharset.GBK);
System.out.println(&再把UTF-8码的字符串转换成GBK码: & + gbk);
System.out.println();
String utf16be = test.toUTF_16BE(str);
System.out.println(&转换成UTF-16BE码:& + utf16be);
gbk = test.changeCharset(utf16be,ChangeCharset.UTF_16BE, ChangeCharset.GBK);
System.out.println(&再把UTF-16BE码的字符串转换成GBK码: & + gbk);
System.out.println();
String utf16le = test.toUTF_16LE(str);
System.out.println(&转换成UTF-16LE码:& + utf16le);
gbk = test.changeCharset(utf16le,ChangeCharset.UTF_16LE, ChangeCharset.GBK);
System.out.println(&再把UTF-16LE码的字符串转换成GBK码: & + gbk);
System.out.println();
String utf16 = test.toUTF_16(str);
System.out.println(&转换成UTF-16码:& + utf16);
gbk = test.changeCharset(utf16,ChangeCharset.UTF_16LE, ChangeCharset.GBK);
System.out.println(&再把UTF-16码的字符串转换成GBK码: & + gbk);
String s = new String(&中文&.getBytes(&UTF-8&),&UTF-8&);
System.out.println(s);
------------------------------------------------------------------------------------------------------------------&&&&&&& java中的String类是按照unicode进行编码的,当使用String(byte[] bytes, String encoding)构造字符串时,encoding所指的是bytes中的数据是按照那种方式编码的,而不是最后产生的String是什么编码方式,换句话说,是让系统把bytes中的数据由encoding编码方式转换成unicode编码。如果不指明,bytes的编码方式将由jdk根据操作系统决定。&&&&&&& 当我们从文件中读数据时,最好使用InputStream方式,然后采用String(byte[] bytes, String encoding)指明文件的编码方式。不要使用Reader方式,因为Reader方式会自动根据jdk指明的编码方式把文件内容转换成unicode编码。&&&&&&& 当我们从数据库中读文本数据时,采用ResultSet.getBytes()方法取得字节数组,同样采用带编码方式的字符串构造方法即可。ResultSbytep[] bytes = rs.getBytes();String str = new String(bytes, &gb2312&);不要采取下面的步骤。ResultSString str = rs.getString();str = new String(str.getBytes(&iso8859-1&), &gb2312&);&&&&&&& 这种编码转换方式效率底。之所以这么做的原因是,ResultSet在getString()方法执行时,默认数据库里的数据编码方式为iso8859-1。系统会把数据依照iso8859-1的编码方式转换成unicode。使用str.getBytes(&iso8859-1&)把数据还原,然后利用new String(bytes, &gb2312&)把数据从gb2312转换成unicode,中间多了好多步骤。&&&&&&& 从HttpRequest中读参数时,利用reqeust.setCharacterEncoding()方法设置编码方式,读出的内容就是正确的了。
本文已收录于以下专栏:
相关文章推荐
首先感谢大家的支持!
今天我们来讲一下,微信怎么接受消息。
接受消息是指:普通用户(也就是关注了我们订阅号或者服务号的用户)发送信息给我们的订阅号或者服务号,我们要接收的就是这个消息。
这个消息一般分...
如果大家下载了weixin4j的话,那么这个工具类对大家使用weixin4j将是一个非常好用的工具类。
首先我创建了一个数据表,来存放access_token
Java 正确的做字符串编码转换
字符串的内部表示?
字符串在java中统一用unicode表示( 即utf-16 LE) ,
对于 String s = "你好哦!";
...
Java 正确的做字符串编码转换
字符串的内部表示?
字符串在java中统一用unicode表示( 即utf-16 LE) ,
对于 String s = "你好哦!";
如果源码文件是GB...
import java.io.UnsupportedEncodingE
* 转换字符串的编码
public class ChangeCharset {
字符串的内部表示?
字符串在java中统一用unicode表示( 即utf-16 LE) ,
对于 String s = "你好哦!";
如果源码文件是GBK编码, 操作系统(windows)...
转一篇关于字符串编码的文章,写的比较详细。
-----------------------------------------------------------------------------...
import java.io.UnsupportedEncodingE
* 转换字符串的编码
public class ChangeCharset {
分享万能java字符串编码转换工具类
源代码下载地址:/share/0832.htm...
package com.zuidaima.
import java.io.UnsupportedEncodingE...
他的最新文章
讲师:钟钦成
讲师:宋宝华
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)使用mp4v2将aac音频h264视频数据封装成mp4开发心得 - CSDN博客
使用mp4v2将aac音频h264视频数据封装成mp4开发心得
这阵子在捣鼓一个将游戏视频打包成本地可播放文件的模块。开始使用avi作为容器,弄了半天无奈avi对aac的支持实在有限,在播放时音视频时无法完美同步。
关于这点avi文档中有提到:
For AAC, one RAW AAC frame usually spans over 1024 samples. However, depending on
the source container (e.g. ADTS), it is theoretically possible that you are not able to extract
packets of equal duration from your source le. In this case, it is highly recommended not
to mux the AAC stream into AVI, but report a fatal error instead.
因此建议大家不要用avi打包aac,如果实在需要avi格式,可以换成mp3。
言归正传,下面重点说说mp4打包时遇到的几个问题,希望对后来开发这方面的朋友能有帮助,少走弯路。
首先需要下载编译开源的mp4v2库。这里一般没什么问题,值得一提的是,mp4v2静态库会导出函数符号。如果你想让程序瘦身,可以这么做在windows的工程属性中去掉MP4V2_EXPORTS预定义,添加MP4V2_USE_STATIC_LIB,这样最终的程序可以小100多KB。
mp4v2在vc2008下编译release版会在link时出现link内部错误(我遇到了,不知道其他人是否也遇到),需要在工程中去掉link时优化,再编译即可。
使用mp4v2打包音视频的具体步骤网上已经有很多例子,不再此啰嗦了,就说说需要注意的几点吧。
1、音频aac不需要包含adts头,即在设置faac选项时:
struConfig.outputFormat = 0; /* Bitstream output format (0 = R 1 = ADTS) */
如果你包含了这个头,我测试下来迅雷播放器可以支持,但是百度影音、暴风影音放出来没声音。(ps,我整个开发过程下来迅雷播放器支持度最好,百度和暴风影音在格式设置错误情况下会出现崩溃和无声音现象,绝非广告)
2、MP4AddAudioTrack时,注意第三个参数sampleDuration要设置正确。如果每次添加的音频数据样本数相同,可以在这里先设置好。mp4v2建议把刻度设置为采样率,这样第三个参数就是每次送入数据块的样本数。这个数据可以在编码aac时得到,faacEncOpen返回的input样本数如果是2048,那么双通道实际就是1024。
3、设置完这些参数后,本以为万事大吉,但是播放器放出来还是没有声音。那就需要用MP4SetTrackESConfiguration设置音频解码信息。音频解码信息怎么来,可以从faac里faacEncGetDecoderSpecificInfo得到,下面是我的代码:
unsigned int CAACCodec::GetDecoderSpecificInfo(unsigned char * & apInfo)
& & if ( m_hCodec == NULL )
& & & & return 0;
& & unsigned long uLen = 0;
& & faacEncGetDecoderSpecificInfo(m_hCodec, &apInfo, &uLen);
& & return uL
将返回的信息,再用MP4SetTrackESConfiguration设置到音频track里去就ok了。
这里有个问题还要注意下,解码信息这块内存,是faac用malloc方式分配出来的,所以你不要忘记free它,否则会造成内存泄露(虽然很小,才2字节)
19:34 379人阅读
杂项(5)&
MP4录制程序是根据mpeg4ip中mpeg4ip-1.5.0.1\server\mp4live\file_mp4_recorder.cpp文件改的。程序支持h264+aac(raw
流)的写入方式,用到了动态库mp4v2-2.0.0,不要用mpeg4ip中那个较老的版本,因为在录制大文件时会有效率问题,下面是一些mp4v2接口的简介。
MP4FileHandle MP4Create (const char* fileName,uint32_t& flags)
功能:创建MP4文件句柄。
&返回:MP4文件句柄。
&参数:fileName
要录制的MP4文件名;flags
创建文件类型,如果要创建普通文件用默认值0就可以,如要录制大于4G的MP4文件此处要设置MP4_CREATE_64BIT_DATA。
bool MP4SetTimeScale( MP4FileHandle hFile, uint32_t value )
功能:设置时间标度。
返回:成功返回true,失败返回false。
参数:hFile MP4文件句柄,value
要设置的值(每秒的时钟ticks数)。
MP4TrackId MP4AddH264VideoTrack(MP4FileHandle hFile,
&& & & & & & & & & & & & & & & & & & uint32_t timeScale,
&& & & & & & & & & & & & & & & & & & MP4Duration sampleDuration,
&& & & & & & & & & & & & & & & & & & uint16_t width,
& & & & & & & & & & & & & & & & & & & uint16_t height,
&& & & & & & & & & & & & & & & & & & uint8_t AVCProfileIndication,
&& & & & & & & & & & & & & & & & & & uint8_t profile_compat,
&& & & & & & & & & & & & & & & & & & uint8_t AVCLevelIndication,
&& & & & & & & & & & & & & & & & & & uint8_t sampleLenFieldSizeMinusOne)
功能:添加h264视频track。
返回:返回track id号。
参数:hFile MP4文件句柄,timeScale
视频每秒的ticks数(如90000),sampleDuration
设置为 MP4_INVALID_DURATION,width height
视频的宽高,AVCProfileIndication profile (baseline profile, main profile, etc. see),profile_compat compatible profile,AVCLevelIndication
levels,sampleLenFieldSizeMinusOne
注意: AVCProfileIndication,profile_compat, AVCLevelIndication,这三个参数值是在h264流中得到的。
MP4TrackId MP4AddAudioTrack(
& & & & MP4FileHandle hFile,
& & & & uint32_t timeScale,
& & & & MP4Duration sampleDuration,
& & & & uint8_t audioType)
&功能:添加音频(aac)track。
&返回:返回track id号。
&参数:hFile MP4句柄,timeScale音频每秒的ticks数(如16000),下面两参数设置为MP4_INVALID_DURATION和MP4_MPEG4_AUDIO_TYPE。
bool MP4SetTrackESConfiguration(
&& & & MP4FileHandle& hFile,
&& & & MP4TrackId & & trackId,
&& & & const uint8_t* pConfig,
&& & & uint32_t & & & configSize );
&功能:设置音频解码信息(如果设置错误会导致没有声音)。
&返回:成功返回true,失败返回false。
&参数:hFile 文件句柄,trackId
音频的track id,pConfig
记录解码信息的二进制流,configSize
解码串的长度。
&注意:mpeg4ip
使用faac进行aac音频编码的,在编码时可以调用相应的函数得到二进制串pConfig和长度configSize,但是如果aac不是用faac编码的,这是需要自己填充pConfig,可以参考faac的实现,下面是一个填充结构例子:
前五个字节为 AAC object types& LOW & & 2
接着4个字节为
码率index& & & & 16000& & & 8
接着4个字节为 channels
个数 & & & & & & & & 1
应打印出的正确2进制形式为& 00010 | 1000 | 0001 | 000
& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & 2& & & & & 8& & & & 1
bool MP4WriteSample(
& & MP4FileHandle& hFile,
& & MP4TrackId & & trackId,
& & const uint8_t* pBytes,
& & uint32_t & & & numBytes,
& & MP4Duration& & duration DEFAULT(MP4_INVALID_DURATION),
& & MP4Duration& & renderingOffset DEFAULT(0),
& & bool & & & & & isSyncSample DEFAULT(true) );
功能:写一帧视频数据或写一段音频数据。
返回:成功返回true,失败返回false。
参数:hFile 文件句柄,trackId
音频或视频的track id,pBytes为要写的数据流指针,numBytes为数据字节长度,duration为前一视频帧与当前视频帧之间的ticks数,或这是前一段音频数据和当前音频数据之间的ticks。isSyncSample
对视频来说是否为关键帧。
注意:1,duration这个参数是用来实现音视频同步用的,如果设置错了会造成音视频不同步,甚至会出现crash现象(一般出现在调用MP4Close是crash)。
2,对于视频流MP4WriteSample函数每次调用是录制前一帧数据,用当前帧的时间戳和前一帧的时间戳计算duration值,然后把当前帧保存下来用做下次调用MP4WriteSample时用,写音频数据一样。
void MP4AddH264SequenceParameterSet(
& & MP4FileHandle& hFile,
& & MP4TrackId & & trackId,
& & const uint8_t* pSequence,
& & uint16_t & & & sequenceLen );
void MP4AddH264PictureParameterSet(
& & MP4FileHandle& hFile,
& & MP4TrackId & & trackId,
& & const uint8_t* pPict,
& & uint16_t & & & pictLen );
功能:添加序列参数集,添加图像参数集。
参数:hFile
文件句柄,trackId 视频track id,pSequence和pPict为要写入的序列图像参数集的数据指针,sequenceLen和pictLen为串长度。
注意:当检测到序列参数集或图像参数集更新时要调用MP4AddH264SequenceParameterSet或MP4AddH264PictureParameterSet进行更新。
void MP4Close(
& & MP4FileHandle hFile,
& & uint32_t& & flags DEFAULT(0) );
功能:关闭以打开的MP4文件。
参数:hFile 文件句柄,flags
是否允许在关闭MP4文件前做一些额外的优化处理。
注意:在录制较小的MP4文件时可以把flags设置为默认值,如果录制较大的文件最好把flags设置为MP4_CLOSE_DO_NOT_COMPUTE_BITRATE否则调用MP4Close函数会用掉很长的时间。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
音频编解码·实战篇(1)PCM转至AAC(AAC编码)
作者:柳大·Poechant
博客:邮箱:zhongchao.日期:April 7th, 2012
这里利用FAAC来实现AAC编码。
1 下载安装 FAAC
这里的安装过程是在 Mac 和 Linux
上实现的,Windows可以类似参考。
wget http://downloads.sourceforge.net/faac/faac-1.28.tar.gz
tar zxvf faac-1.28.tar.gz
cd faac-1.28
./configure
sudo make install
如果才用默认的 configure
中的 prefix path,那么安装后的 lib
和 .h 文件分别在/usr/local/lib和/usr/local/include,后面编译的时候会用到。
如果编译过程中发现错误:
mpeg4ip.h:126: error: new declaration ‘char* strcasestr(const char*, const char*)’
解决方法:
从123行开始修改此文件mpeg4ip.h,到129行结束。
#ifdef __cplusplus
extern &C& {
char *strcasestr(const char *haystack, const char *needle);
#ifdef __cplusplus
#ifdef __cplusplus
extern &C++& {
const char *strcasestr(const char *haystack, const char *needle);
#ifdef __cplusplus
2 FAAC API
2.1 Open FAAC engine
Prototype:
faacEncHandle faacEncOpen & & & & & & & //
返回一个FAAC的handle
(& & & & & & & & & &
& & unsigned long & nSampleRate,& & & & //
采样率,单位是bps
& & unsigned long & nChannels,& & & & & //
声道,1为单声道,2为双声道
& & unsigned long & &nInputSamples, & & //
传引用,得到每次调用编码时所应接收的原始数据长度
& & unsigned long & &nMaxOutputBytes& & //
传引用,得到每次调用编码时生成的AAC数据的最大长度
2.2 Get/Set encoding configuration
Prototype:
获取编码器的配置:
faacEncConfigurationPtr faacEncGetCurrentConfiguration //
得到指向当前编码器配置的指针
& & faacEncHandle hEncoder& // FAAC的handle
设定编码器的配置:
int FAACAPI faacEncSetConfiguration
& & faacDecHandle hDecoder, & & & & //
此前得到的FAAC的handle
& & faacEncConfigurationPtr config& // FAAC编码器的配置
2.3 Encode
Prototype:
int faacEncEncode
& & faacEncHandle hEncoder, & & // FAAC的handle
& & short *inputBuffer, & & & & // PCM原始数据
& & unsigned int samplesInput,& //
调用faacEncOpen时得到的nInputSamples值
& & unsigned char *outputBuffer,//
至少具有调用faacEncOpen时得到的nMaxOutputBytes字节长度的缓冲区
& & unsigned int bufferSize & & // outputBuffer缓冲区的实际大小
2.4 Close FAAC engine
void faacEncClose
& & faacEncHandle hEncoder& //
此前得到的FAAC handle
3.1 做什么准备?
采样率,声道数(双声道还是单声道?),还有你的PCM的单个样本是8位的还是16位的?
3.2 开启FAAC编码器,做编码前的准备
调用faacEncOpen开启FAAC编码器后,得到了单次输入样本数nInputSamples和输出数据最大字节数nMaxOutputBytes;根据nInputSamples和nMaxOutputBytes,分别为PCM数据和将要得到的AAC数据创建缓冲区;调用faacEncGetCurrentConfiguration获取当前配置,修改完配置后,调用faacEncSetConfiguration设置新配置。
3.3 开始编码
调用faacEncEncode,该准备的刚才都准备好了,很简单。
关闭编码器,另外别忘了释放缓冲区,如果使用了文件流,也别忘记了关闭。
4 测试程序
4.1 完整代码
将PCM格式音频文件/home/michael/Development/testspace/in.pcm转至AAC格式文件/home/michael/Development/testspace/out.aac。
#include &faac.h&
#include &stdio.h&
typedef unsigned long & ULONG;
typedef unsigned int& & UINT;
typedef unsigned char & BYTE;
typedef char& & & & & & _TCHAR;
int main(int argc, _TCHAR* argv[])
& & ULONG nSampleRate = 11025;& //
& & UINT nChannels = 1; & & & & //
& & UINT nPCMBitSize = 16;& & & //
单样本位数
& & ULONG nInputSamples = 0;
& & ULONG nMaxOutputBytes = 0;
& & int nR
& & faacEncHandle hE
& & faacEncConfigurationPtr pC&
& & int nBytesR
& & int nPCMBufferS
& & BYTE* pbPCMB
& & BYTE* pbAACB
& & FILE* fpIn; // PCM file for input
& & FILE* fpO // AAC file for output
& & fpIn = fopen(&/home/michael/Development/testspace/in.pcm&, &rb&);
& & fpOut = fopen(&/home/michael/Development/testspace/out.aac&, &wb&);
& & // (1) Open FAAC engine
& & hEncoder = faacEncOpen(nSampleRate, nChannels, &nInputSamples, &nMaxOutputBytes);
& & if(hEncoder == NULL)
& & & & printf(&[ERROR] Failed to call faacEncOpen()\n&);
& & & & return -1;
& & nPCMBufferSize = nInputSamples * nPCMBitSize / 8;
& & pbPCMBuffer = new BYTE [nPCMBufferSize];
& & pbAACBuffer = new BYTE [nMaxOutputBytes];
& & // (2.1) Get current encoding configuration
& & pConfiguration = faacEncGetCurrentConfiguration(hEncoder);
& & pConfiguration-&inputFormat = FAAC_INPUT_16BIT;
& & // (2.2) Set encoding configuration
& & nRet = faacEncSetConfiguration(hEncoder, pConfiguration);
& & for(int i = 0; 1; i++)
& & & & // 读入的实际字节数,最大不会超过nPCMBufferSize,一般只有读到文件尾时才不是这个值
& & & & nBytesRead = fread(pbPCMBuffer, 1, nPCMBufferSize, fpIn);
& & & & // 输入样本数,用实际读入字节数计算,一般只有读到文件尾时才不是nPCMBufferSize/(nPCMBitSize/8);
& & & & nInputSamples = nBytesRead / (nPCMBitSize / 8);
& & & & // (3) Encode
& & & & nRet = faacEncEncode(
& & & & hEncoder, (int*) pbPCMBuffer, nInputSamples, pbAACBuffer, nMaxOutputBytes);
& & & & fwrite(pbAACBuffer, 1, nRet, fpOut);
& & & & printf(&%d: faacEncEncode returns %d\n&, i, nRet);
& & & & if(nBytesRead &= 0)
& & & & & &
& & while(1)
& & & & // (3) Flushing
& & & & nRet = faacEncEncode(
& & & & hEncoder, (int*) pbPCMBuffer, 0, pbAACBuffer, nMaxOutputBytes);
& & & & if(nRet &= 0)
& & & & & &
& & // (4) Close FAAC engine
& & nRet = faacEncClose(hEncoder);
& & delete[] pbPCMB
& & delete[] pbAACB
& & fclose(fpIn);
& & fclose(fpOut);
& & //getchar();
& & return 0;
4.2 编译运行
将上述代码保存为“pcm2aac.cpp”文件,然后编译:
g++ pcm2aac.cpp -o pcm2aac -L/usr/local/lib -lfaac -I/usr/local/include
然后就生成了out.aac文件了,听听看吧!~
5 Reference
转载请注明来自柳大的CSDN博客:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
14:09 2843人阅读
我的程序是根据faac 1.28
库中的frontend目录下的faac的例子改的。
下面是程序的运行流程:
首先调用faacEncHandle hEncoder=faacEncOpen(samplerate,channels,& samplesInput,
&maxBytesOutput);
1.打开aac编码引擎,创建aac编码句柄。
参数 samplerate 为要编码的音频pcm流的采样率,channels为要编码的音频pcm流的的频道数(原有的例子程序是从wav文件中读出这些信息),sampleInput在编码时要用到,意思是每次要编码的采样数,参数maxBytesOutput为编码时输出地最大字节数。
2.然后在设置一些编码参数,如
int version=MPEG4;& & //设置版本,录制MP4文件时要用MPEG4
int objecttype=LOW;& & //编码类型
int midside=1;& & & & & //M/S编码
int usetns=DEFAULT_TNS; & //瞬时噪声定形(temporal noise shaping,TNS)滤波器
int shortctl=SHORTCTL_NORMAL;
int inputformat=FAAC_INPUT_16BIT;& //输入数据类型
int outputformat=RAW_STREAM; //录制MP4文件时,要用raw流。检验编码是否正确时可设
&& & & & & & & & & & & & & & & & & & & & & & & & & & & & & //置为adts传输流,把aac
流写入.aac文件中,如编码正确
& & & & & & & & & & & & & & & & & & & & & & & & & & & & & //用千千静听就可以播放。
其他的参数可根据例子程序设置。
设置完参数后就调用faacEncSetConfiguration(hEncoder, aacFormat)设置编码参数。
3.如编码完的aac流要写入MP4文件时,要调用
faacEncGetDecoderSpecificInfo(hEncoder,&(ASC), &(ASCLength));//得到解码信息
&& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & //(mpeg4ip mp4
录制使用)
此函数支持MPEG4版本,得到的ASC
和ACSLength
数据在录制MP4(mpegip库)文件时用。
4.然后就是编码了,每次从实时的pcm音频队列中读出samplesInput* channels*(量化位数/8),
字节数的pcm数据。然后再把得到pcm流转变一下存储位数,我是转化为16位的了,这部分
可以根据例子程序写一个函数,这是我写的一个,
size_t read_int16(AACInfo *sndf, int16_t *outbuf, size_t num, unsigned char *inputbuf)
&& & & size_t i=0,j=0;
&& & & unsigned char bufi[8];
&& & & while(i&num)
& & & & & & & & memcpy(bufi,inputbuf+j,sndf-&samplebytes);
&& & & & & & & j+=sndf-&
& & & & & & & int16_t s=((int16_t*)bufi)[0];
&& & & & & & outbuf[i]=s;
&& & & & & & i++;
也可以写一个read_float32(AACInfo *sndf, float *outbuf, size_t num ,unsigned char *inputbuf),
和size_t read_int24(AACInfo *sndf, int32_t *outbuf, size_t num, unsigned char *inputbuf)。
处理完数据转换后就调用
bytesWritten = faacEncEncode(hEncoder,
& & & & & & & & & & & & & & & & & & & & & & & & & & & & (int *)pcmbuf,
& & & & & & & & & & & & & & & & & & & & & & & & & & & & samplesInput,
& & & & & & & & & & & & & & & & & & & & & & & & & & & & outbuff,
& & & & & & & & & & & & & & & & & & & & & & & & & & & & maxbytesoutput);
进行编码,pcmbuf为转换后的pcm流数据,samplesInput为调用faacEncOpen时得到的输入采样数,outbuff为编码后的数据buff,maxbytesoutput为调用faacEncOpen时得到的最大输出字节数。然后每次从outbuff中得到编码后的aac数据流,放到数据队列就行了,如果还要录制MP4文件,在编码完samplesInput(一帧)个采样数时,打上时间戳(mpegip库用于音视频同步)后再放到输出队列中。如果想测试看编码的aac流是否正确,设置输出格式为ADTS_STREAM,把aac数据写入到.aac文件中,看能否用千千静听播放。
5.释放资源,调用faacEncClose(hEncoder);就行了
Mp4v2实现h264+aac打包成Mp4视频文件
使用mp4v2实现录制mp4视频,需要准备如下信息:
1、获取mp4v2源码并编译成库文件,对于mp4v2的编译可以看前面的文章android 编译mp4v2 2.0.0生成动态库 ;
2、获取h264数据中的sps和pps数据,如果不会的话可以查看前面的文章& 点击打开链接;
3、获取音频解码信息,在调用MP4SetTrackESConfiguration使用,具体的获取方式一种通过faac获取,方法faacEncGetDecoderSpecificInfo(hEncoder,&(ASC), &(ASCLength));//得到解码信息另一种查看aac音频源码,并并对照aac的adts头格式分析:
前五个字节为 AAC object types& LOW & & 2 &
接着4个字节为 码率index& & & & 16000& & & 8 &
接着4个字节为 channels 个数 & & & & & & & & 1 &
应打印出的正确2进制形式为& 00010 | 1000 | 0001 | 000 &
& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & 2& & & & & 8& & & & 1 &
前五个字节为 AAC object types& LOW & & 2 &
接着4个字节为 码率index& & & & 16000& & & 8 &
接着4个字节为 channels 个数 & & & & & & & & 1 &
应打印出的正确2进制形式为& 00010 | 1000 | 0001 | 000 &
& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & 2& & & & & 8& & & & 1 &
所以为(20,8)
4、规定时间刻度问题,一般网上都是设置90000,这个90000是指1秒的tick数,其实也就是把1秒中分为90000份,在添加音视频的函数中
durationMP4_INVALID_DURATION
bool MP4WriteSample( &
MP4FileHandle hFile, &
MP4TrackId trackId, &
u_int8_t* pBytes, &
u_int32_t numBytes, &
MP4Duration duration = MP4_INVALID_DURATION, &
MP4Duration renderingOffset = 0, &
bool isSyncSample = true & //如果是视频,此处是指当前视频帧是否是关键帧,如果是则为1,如果不是则为0 &
bool MP4WriteSample( &
MP4FileHandle hFile, &
MP4TrackId trackId, &
u_int8_t* pBytes, &
u_int32_t numBytes, &
MP4Duration duration = MP4_INVALID_DURATION, &
MP4Duration renderingOffset = 0, &
bool isSyncSample = true & //如果是视频,此处是指当前视频帧是否是关键帧,如果是则为1,如果不是则为0 &
其中duration这个参数是指视频帧存在的时间,在90000这个刻度上存在的时间,如果用户确定录像时的音频视频帧是按固定速率的,那么在这里可以设置MP4_INVALID_DURATION,这时mp4v2就会使用下面的函数中的时间刻度
MP4AddH264VideoTrack(MP4FileHandle hFile, &
& & & & & & & & & & & & & & & & & & uint32_t timeScale, &
& & & & & & & & & & & & & & & & & & MP4Duration sampleDuration, &
& & & & & & & & & & & & & & & & & & uint16_t width, &
& & & & & & & & & & & & & & & & & & uint16_t height, &
& & & & & & & & & & & & & & & & & & uint8_t AVCProfileIndication, &
& & & & & & & & & & & & & & & & & & uint8_t profile_compat, &
& & & & & & & & & & & & & & & & & & uint8_t AVCLevelIndication, &
& & & & & & & & & & & & & & & & & & uint8_t sampleLenFieldSizeMinusOne) &
sampleDuration为视频的固定的视频帧的显示时间,计算的方法为timeScale(90000)* during(这个值是当前视频帧的采集时间 - 上一帧的视频 &
采集时间)/1000,公式也可以改为timeScale(90000)/fps(码率例如20f) &
sampleDuration &
MP4TrackId MP4AddAudioTrack( &
MP4FileHandle hFile, &
u_int32_t timeScale, &
u_int32_t sampleDuration, &
u_int8_t audioType = MP4_MPEG4_AUDIO_TYPE &
sampleDuration 是音频的音频帧在时间刻度上存在的时间,这里的timeScale为音频的采样时间,例如,计算方法给上面的视频一样的。 &
sampleDuration主要作用是用于音视频同步问题。 &
5、mp4v2录制视频中h264的格式要求:NAL长度+NAL数据,如果传过来的数据没有0x则是纯数据 &
(1)h264流中的NAL,头四个字节是0x; &
(2)mp4中的h264track,头四个字节要求是NAL的长度,并且是大端顺序; &
(3)mp4v2很可能针对此种情况并没有做处理,所以写到mp4文件中的每个NAL头四个字节还是0x. &
因此如果传过来的h264数据是纯数据的话则需要如下修改: &
& int nalsize = frameS &
& & & buf[0] = (nalsize&0xff000000)&&24; &
& & & buf[1] = (nalsize&0x00ff0000)&&16; &
& & & buf[2] = (nalsize&0x0000ff00)&&8; &
& & & buf[3] = nalsize&0x000000如果头部格式有其他的,则按照上面的方式偏移到纯数据位置。 &
6、mp4v2录制视频中aac的格式要求:有时远程传过来的aac数据的格式为adts+aac纯数据,则需要将adts部分去掉,即需要偏移7个字节的单位 &
下面就开始编写如何调用mp4v2库的方法: &
#include &stdio.h& &
#include &string.h& &
#include &../mp4v2/mp4v2.h& &
#include &AppCameraShooting.h& &
MP4TrackI &
MP4TrackI &
MP4FileHandle fileH &
unsigned char sps_pps_640[17] = {0x67, 0x42, 0x40, 0x1F, 0x96 ,0x54, 0x05, 0x01, 0xED, 0x00, 0xF3, 0x9E, 0xA0, 0x68, 0xCE, 0x38, 0x80}; //存储sps和pps &
int video_width = 640; &
int video_height = 480; &
//视频录制的调用,实现初始化 &
& & JNIEXPORT bool JNICALL Java_com_seuic_jni_AppCameraShooting_mp4init &
(JNIEnv *env, jclass clz, jstring title, jint type) &
& & const char* local_title = (*env)-&GetStringUTFChars(env,title, NULL); &
& & //创建mp4文件 &
& & fileHandle = MP4Create(local_title, 0); &
& & if(fileHandle == MP4_INVALID_FILE_HANDLE) &
& & memcpy(sps_pps, sps_pps_640, 17); &
& & video_width = 640; &
& & video_height = 480; &
& & //设置mp4文件的时间单位 &
& & MP4SetTimeScale(fileHandle, 90000); &
& & //创建视频track //根据ISO/IEC 14496-10 可知sps的第二个,第三个,第四个字节分别是 AVCProfileIndication,profile_compat,AVCLevelIndication & & 其中90000/20& 中的20&是fps &
& & video = MP4AddH264VideoTrack(fileHandle, 9/20, video_width, video_height, sps_pps[1], sps_pps[2], sps_pps[3], 3); &
& & if(video == MP4_INVALID_TRACK_ID) &
& & & & MP4Close(fileHandle, 0); &
& & audio = MP4AddAudioTrack(fileHandle, 1, MP4_MPEG2_AAC_LC_AUDIO_TYPE); &
& & if(audio == MP4_INVALID_TRACK_ID) &
& & & & MP4Close(fileHandle, 0); &
& & //设置sps和pps &
& & MP4AddH264SequenceParameterSet(fileHandle, video, sps_pps, 13); &
& & MP4AddH264PictureParameterSet(fileHandle, video, sps_pps+13, 4); &
& & MP4SetVideoProfileLevel(fileHandle, 0x7F); &
& & MP4SetAudioProfileLevel(fileHandle, 0x02); &
& & MP4SetTrackESConfiguration(fileHandle, audio, &ubuffer[0], 2); &
& & (*env)-&ReleaseStringUTFChars(env, title, local_title); &
& & //添加视频帧的方法 &
& & JNIEXPORT void JNICALL Java_com_seuic_jni_AppCameraShooting_mp4packVideo &
(JNIEnv *env, jclass clz, jbyteArray data, jint size, jint keyframe) &
& & unsigned char *buf = (unsigned char *)(*env)-&GetByteArrayElements(env, data, JNI_FALSE); &
& & if(video_type == 1){ &
& & & & int nalsize = &
& & & & buf[0] = (nalsize & 0xff000000) && 24; &
& & & & buf[1] = (nalsize & 0x00ff0000) && 16; &
& & & & buf[2] = (nalsize & 0x0000ff00) && 8; &
& & & & buf[3] =& nalsize & 0x000000 &
& & & & MP4WriteSample(fileHandle, video, buf, size, MP4_INVALID_DURATION, 0, keyframe); &
& & (*env)-&ReleaseByteArrayElements(env, data, (jbyte *)buf, 0); &
& & //添加音频帧的方法 &
& & JNIEXPORT void JNICALL Java_com_seuic_jni_AppCameraShooting_mp4packAudio &
(JNIEnv *env, jclass clz, jbyteArray data, jint size) &
& & uint8_t *bufaudio = (uint8_t *)(*env)-&GetByteArrayElements(env, data, JNI_FALSE); &
& & MP4WriteSample(fileHandle, audio, &bufaudio[7], size-7, MP4_INVALID_DURATION, 0, 1); //减去7为了删除adts头部的7个字节 &
& & (*env)-&ReleaseByteArrayElements(env, data, (jbyte *)bufaudio, 0); &
& & //视频录制结束调用 &
& & JNIEXPORT void JNICALL Java_com_seuic_jni_AppCameraShooting_mp4close &
(JNIEnv *env, jclass clz) &
& & MP4Close(fileHandle, 0); &
MP4AddH264VideoTrack(MP4FileHandle hFile, &
& & & & & & & & & & & & & & & & & & uint32_t timeScale, &
& & & & & & & & & & & & & & & & & & MP4Duration sampleDuration, &
& & & & & & & & & & & & & & & & & & uint16_t width, &
& & & & & & & & & & & & & & & & & & uint16_t height, &
& & & & & & & & & & & & & & & & & & uint8_t AVCProfileIndication, &
& & & & & & & & & & & & & & & & & & uint8_t profile_compat, &
& & & & & & & & & & & & & & & & & & uint8_t AVCLevelIndication, &
& & & & & & & & & & & & & & & & & & uint8_t sampleLenFieldSizeMinusOne) &
sampleDuration为视频的固定的视频帧的显示时间,计算的方法为timeScale(90000)* during(这个值是当前视频帧的采集时间 - 上一帧的视频 &
采集时间)/1000,公式也可以改为timeScale(90000)/fps(码率例如20f) &
sampleDuration &
MP4TrackId MP4AddAudioTrack( &
MP4FileHandle hFile, &
u_int32_t timeScale, &
u_int32_t sampleDuration, &
u_int8_t audioType = MP4_MPEG4_AUDIO_TYPE &
sampleDuration 是音频的音频帧在时间刻度上存在的时间,这里的timeScale为音频的采样时间,例如,计算方法给上面的视频一样的。 &
sampleDuration主要作用是用于音视频同步问题。 &
5、mp4v2录制视频中h264的格式要求:NAL长度+NAL数据,如果传过来的数据没有0x则是纯数据 &
(1)h264流中的NAL,头四个字节是0x; &
(2)mp4中的h264track,头四个字节要求是NAL的长度,并且是大端顺序; &
(3)mp4v2很可能针对此种情况并没有做处理,所以写到mp4文件中的每个NAL头四个字节还是0x. &
因此如果传过来的h264数据是纯数据的话则需要如下修改: &
& int nalsize = frameS &
& & & buf[0] = (nalsize&0xff000000)&&24; &
& & & buf[1] = (nalsize&0x00ff0000)&&16; &
& & & buf[2] = (nalsize&0x0000ff00)&&8; &
& & & buf[3] = nalsize&0x000000如果头部格式有其他的,则按照上面的方式偏移到纯数据位置。 &
6、mp4v2录制视频中aac的格式要求:有时远程传过来的aac数据的格式为adts+aac纯数据,则需要将adts部分去掉,即需要偏移7个字节的单位 &
下面就开始编写如何调用mp4v2库的方法: &
#include &stdio.h& &
#include &string.h& &
#include &../mp4v2/mp4v2.h& &
#include &AppCameraShooting.h& &
MP4TrackI &
MP4TrackI &
MP4FileHandle fileH &
unsigned char sps_pps_640[17] = {0x67, 0x42, 0x40, 0x1F, 0x96 ,0x54, 0x05, 0x01, 0xED, 0x00, 0xF3, 0x9E, 0xA0, 0x68, 0xCE, 0x38, 0x80}; //存储sps和pps &
int video_width = 640; &
int video_height = 480; &
//视频录制的调用,实现初始化 &
& & JNIEXPORT bool JNICALL Java_com_seuic_jni_AppCameraShooting_mp4init &
(JNIEnv *env, jclass clz, jstring title, jint type) &
& & const char* local_title = (*env)-&GetStringUTFChars(env,title, NULL); &
& & //创建mp4文件 &
& & fileHandle = MP4Create(local_title, 0); &
& & if(fileHandle == MP4_INVALID_FILE_HANDLE) &
& & memcpy(sps_pps, sps_pps_640, 17); &
& & video_width = 640; &
& & video_height = 480; &
& & //设置mp4文件的时间单位 &
& & MP4SetTimeScale(fileHandle, 90000); &
& & //创建视频track //根据ISO/IEC 14496-10 可知sps的第二个,第三个,第四个字节分别是 AVCProfileIndication,profile_compat,AVCLevelIndication & & 其中90000/20& 中的20&是fps &
& & video = MP4AddH264VideoTrack(fileHandle, 9/20, video_width, video_height, sps_pps[1], sps_pps[2], sps_pps[3], 3); &
& & if(video == MP4_INVALID_TRACK_ID) &
& & & & MP4Close(fileHandle, 0); &
& & audio = MP4AddAudioTrack(fileHandle, 1, MP4_MPEG2_AAC_LC_AUDIO_TYPE); &
& & if(audio == MP4_INVALID_TRACK_ID) &
& & & & MP4Close(fileHandle, 0); &
& & //设置sps和pps &
& & MP4AddH264SequenceParameterSet(fileHandle, video, sps_pps, 13); &
& & MP4AddH264PictureParameterSet(fileHandle, video, sps_pps+13, 4); &
& & MP4SetVideoProfileLevel(fileHandle, 0x7F); &
& & MP4SetAudioProfileLevel(fileHandle, 0x02); &
& & MP4SetTrackESConfiguration(fileHandle, audio, &ubuffer[0], 2); &
& & (*env)-&ReleaseStringUTFChars(env, title, local_title); &
& & //添加视频帧的方法 &
& & JNIEXPORT void JNICALL Java_com_seuic_jni_AppCameraShooting_mp4packVideo &
(JNIEnv *env, jclass clz, jbyteArray data, jint size, jint keyframe) &
& & unsigned char *buf = (unsigned char *)(*env)-&GetByteArrayElements(env, data, JNI_FALSE); &
& & if(video_type == 1){ &
& & & & int nalsize = &
& & & & buf[0] = (nalsize & 0xff000000) && 24; &
& & & & buf[1] = (nalsize & 0x00ff0000) && 16; &
& & & & buf[2] = (nalsize & 0x0000ff00) && 8; &
& & & & buf[3] =& nalsize & 0x000000 &
& & & & MP4WriteSample(fileHandle, video, buf, size, MP4_INVALID_DURATION, 0, keyframe); &
& & (*env)-&ReleaseByteArrayElements(env, data, (jbyte *)buf, 0); &
& & //添加音频帧的方法 &
& & JNIEXPORT void JNICALL Java_com_seuic_jni_AppCameraShooting_mp4packAudio &
(JNIEnv *env, jclass clz, jbyteArray data, jint size) &
& & uint8_t *bufaudio = (uint8_t *)(*env)-&GetByteArrayElements(env, data, JNI_FALSE); &
& & MP4WriteSample(fileHandle, audio, &bufaudio[7], size-7, MP4_INVALID_DURATION, 0, 1); //减去7为了删除adts头部的7个字节 &
& & (*env)-&ReleaseByteArrayElements(env, data, (jbyte *)bufaudio, 0); &
& & //视频录制结束调用 &
& & JNIEXPORT void JNICALL Java_com_seuic_jni_AppCameraShooting_mp4close &
(JNIEnv *env, jclass clz) &
& & MP4Close(fileHandle, 0); &
本文已收录于以下专栏:
相关文章推荐
前言在能够使用原生的情况下,博主是绝对不会尝试陌生的jni编程的。但是,偏偏android原生的MediaMuxer(合成器)使用有限制不说,在合成的时候出现各种问题,网上的可参考资料也少,绝大多数都...
使用mp4v2实现录制mp4视频,需要准备如下信息:
1、获取mp4v2源码并编译成库文件,对于mp4v2的编译可以看前面的文章android 编译mp4v2 2.0.0生成动态库 ;
/chutianyao/archive//2446140.html
录制程序要添加新功能:录制CMMB电视节目,我们的板卡发送出来的...
MP4录制程序是根据mpeg4ip中mpeg4ip-1.5.0.1\server\mp4live\file_mp4_recorder.cpp文件改的。程序支持h264+aac(raw 流)的写入方式,...
本文介绍Mp4v2的使用,成功将H264 ES文件和AAC文件封装成MP4文件
1. Mp4V2使用VS2013编译
studio9.0\下打开方案
一般情况,编译会出现错误
Ottavio Campana
“question about MP4AddH264VideoTrack。
What's the meaning of the profile_compat and ...
long long getSystemTime() {
ftime(&t);
return 1000 * t.tim...
使用mp4v2实现录制mp4视频,需要准备如下信息:
1、获取mp4v2源码并编译成库文件,对于mp4v2的编译可以看前面的文章android
编译mp4v2 2.0.0生成动态库 ;
MP4录制程序是根据mpeg4ip中mpeg4ip-1.5.0.1\server\mp4live\file_mp4_recorder.cpp文件改的。程序支持h264+aac(raw 流)的写入方式,...
他的最新文章
讲师:钟钦成
讲师:宋宝华
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)

我要回帖

更多关于 jave.视频转mp4 的文章

 

随机推荐