2011-11-21 10:02:18
ril的问题
实际上就是一个android.jar
找的是avC
设备类型和子类型
注册消息和login返回的消息
其他的类型都是2
注册类型 设备类型和设备子类型
MPEG4Writer
没有发送媒体流了
fopen和fdopen
dump 将所有track的内容都dump出来
dump 描述track的是音频还是视频的?
addSource 每个源就是一个track
startTracks 将每个track开启一下
//计算moovbox的大小
int64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
// This implementation is highly experimental/heurisitic.
//
// Statistical analysis shows that metadata usually accounts
// for a small portion of the total file size, usually < 0.6%.
// The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
// where 1MB is the common file size limit for MMS application.
// The default MAX _MOOV_BOX_SIZE value is based on about 3
// minute video recording with a bit rate about 3 Mbps, because
// statistics also show that most of the video captured are going
// to be less than 3 minutes.
// If the estimation is wrong, we will pay the price of wasting
// some reserved space. This should not happen so often statistically.
static const int32_t factor = mUse32BitOffset? 1: 2;
static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024; // 3 KB
static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
int64_t size = MIN_MOOV_BOX_SIZE;
最小是3K
// Max file size limit is set
if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
size = mMaxFileSizeLimitBytes * 6 / 1000;
}
// Max file duration limit is set
if (mMaxFileDurationLimitUs != 0) {
if (bitRate > 0) {
int64_t size2 =
((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000);
if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
// When both file size and duration limits are set,
// we use the smaller limit of the two.
if (size > size2) {
size = size2;
}
} else {
// Only max file duration limit is set
size = size2;
}
}
}
if (size < MIN_MOOV_BOX_SIZE) {
size = MIN_MOOV_BOX_SIZE;
}
// Any long duration recording will be probably end up with
// non-streamable mp4 file.
if (size > MAX_MOOV_BOX_SIZE) {
size = MAX_MOOV_BOX_SIZE;
}
LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated"
" moov size %lld bytes",
mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
return factor * size;
}
首先来说3gp文件相当于一个容器,本身没有什么具体的编码解码规则。
我们可以选择编码方式
- AMR narrow-band:编码简称'samr' 常用与语言片段的压缩,可以对声音片段进行最大程度的压缩,但是失真较大,
如果用在音乐文件上结构常常是无法忍受的。
(详情请参考:3GPP TS 26.071: "Mandatory Speech CODEC speech processing functions; AMR Speech CODEC; General description".)
- AMR wideband:编码简称'sawb' 相对AMR narrow-band来说压缩比降低了,品质有所提升可用来压缩音乐。
(详情请参考:3GPP TS 26.171: "AMR Wideband Speech Codec; General Description".)
宽带
- Extended AMR-WB codec编码简称 'sawp'
(详情请参考:
3GPP TS 26.290: "Extended AMR Wideband codec; Transcoding functions".
3GPP TS 26.304: "ANSI-C code for the Floating-point; Extended AMR Wideband codec".
3GPP TS 26.273: "ANSI-C code for the Fixed-point; Extended AMR Wideband codec".
- Enhanced aacPlus and MPEG-4 AAC codec编码简称 'mp4a'
(详情请参考:
3GPP TS 26.401: "General audio codec audio processing functions; Enhanced aacPlus general audio codec; General description".
3GPP TS 26.410: "General audio codec audio processing functions; Enhanced aacPlus general audio codec; Floating-point ANSI-C code".
3GPP TS 26.411: "General audio codec audio processing functions; Enhanced aacPlus general audio codec; Fixed-point ANSI-C code".
- MPEG-4 video codec编码简称'mp4v'
(详情请参考:ISO/IEC 14496-2:2004: "Information technology – Coding of audio-visual objects – Part 2: Visual".)
- H.263 video codec编码简称'h263'
(详情请参考:ITU-T Recommendation H.263 (01/05): "Video coding for low bit rate communication".)
- H.264 video codec编码简称'avc1'
(详情请参考:ITU-T Recommendation H.264 (03/05): "Advanced video coding for generic audiovisual services"
ISO/IEC 14496-10:2005: "Information technology – Coding of audio-visual objects – Part 10: Advanced Video Coding".)
- 3GPP timed text format 编码简称'tx3g'
(详情请参考:3GPP TS 26.245: "Transparent end-to-end packet switched streaming service (PSS); Timed text format".)
start
如果有文件大小限制,那就是要精确的限制文件大小
到底是使用32位偏移还是使用64位偏移
如果是32位系统,最大文件大小只能是2G
使用2字节的NAL长度,还是使用4字节的NAL长度
如果已经是开始了,那么返回,如果是暂停,直接startTracks
获取时间精度,默认为1000
beginBox("ftyp"); 写入ftyp
beginBox("ftyp");
{
int32_t fileType;
if (param && param->findInt32(kKeyFileType, &fileType) &&
fileType != OUTPUT_FORMAT_MPEG_4) {
writeFourcc("3gp4");
} else {
writeFourcc("isom");
}
}
writeInt32(0);
writeFourcc("isom");
writeFourcc("3gp4");
endBox();
void MPEG4Writer::endBox() {
CHECK(!mBoxes.empty());
off_t offset = *--mBoxes.end();
mBoxes.erase(--mBoxes.end());
if (mWriteMoovBoxToMemory) {
int32_t x = htonl(mMoovBoxBufferOffset - offset);
memcpy(mMoovBoxBuffer + offset, &x, 4);
} else {
fseeko(mFile, offset, SEEK_SET);
writeInt32(mOffset - offset);
mOffset -= 4;
fseeko(mFile, mOffset, SEEK_SET);
}
}
重新写这个头
status_t MPEG4Writer::startWriterThread() {
LOGV("startWriterThread");
mDone = false;
mIsFirstChunk = true;
mDriftTimeUs = 0;
for (List<Track *>::iterator it = mTracks.begin();
it != mTracks.end(); ++it) {
ChunkInfo info;
info.mTrack = *it;
mChunkInfos.push_back(info);
}
全部放入到 chunk中
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&mThread, &attr, ThreadWrapper, this);
pthread_attr_destroy(&attr);
return OK;
}
写封装
void *MPEG4Writer::ThreadWrapper(void *me) {
LOGV("ThreadWrapper: %p", me);
MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
writer->threadFunc();
return NULL;
}
status_t MPEG4Writer::writeOneChunk() {
LOGV("writeOneChunk");
// Find the smallest timestamp, and write that chunk out
// XXX: What if some track is just too slow?
int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
Track *track = NULL;
for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
it != mChunkInfos.end(); ++it) {
if (!it->mChunks.empty()) {
List<Chunk>::iterator chunkIt = it->mChunks.begin();
if (chunkIt->mTimeStampUs < minTimestampUs) {
minTimestampUs = chunkIt->mTimeStampUs;
track = it->mTrack;
}
}
}
if (track == NULL) {
LOGV("Nothing to be written after all");
return OK;
}
if (mIsFirstChunk) {
mIsFirstChunk = false;
}
for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
it != mChunkInfos.end(); ++it) {
if (it->mTrack == track) {
writeFirstChunk(&(*it));
}
}
return OK;
}
chunk
struct ChunkInfo {
Track *mTrack; // Owner
List<Chunk> mChunks; // Remaining chunks to be written
};
addSample_l