我是靠谱客的博主 认真芝麻,这篇文章主要介绍内存、分配-OMXCodec源码分析---part2-by小雨,现在分享给大家,希望可以做个参考。

查了好多资料,发现还是不全,干脆自己整理吧,至少保证在我的做法正确的,以免误导读者,也是给自己做个记录吧!

    书接前文

    omxcodec创立完了当前,前面就要开始读取数据,码解,送出数据一系列的作操

    接着看initvideodecoder,create omxcodec当前,调用了strat法方,代码如下

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
{ CODEC_LOGV("OMXCodec::start "); Mutex::Autolock autoLock(mLock); if (mState != LOADED) { return UNKNOWN_ERROR; } sp<MetaData> params = new MetaData; if (mQuirks & kWantsNALFragments) { params->setInt32(kKeyWantsNALFragments, true); } if (meta) { int64_t startTimeUs = 0; int64_t timeUs; if (meta->findInt64(kKeyTime, &timeUs)) { startTimeUs = timeUs; } params->setInt64(kKeyTime, startTimeUs); } status_t err = mSource->start(params.get()); if (err != OK) { return err; } mCodecSpecificDataIndex = 0; mInitialBufferSubmit = true; mSignalledEOS = false; mNoMoreOutputData = false; mOutputPortSettingsHaveChanged = false; mSeekTimeUs = -1; mSeekMode = ReadOptions::SEEK_CLOSEST_SYNC; mTargetTimeUs = -1; mFilledBuffers.clear(); mPaused = false; err = init(); if (err != OK) { ALOGV("init failed, so stop source"); mSource->stop(); } return err; }

    初始化一些参数,init数函接着看

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{ // mLock is held. CHECK_EQ((int)mState, (int)LOADED); status_t err; if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) { err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle); setState(LOADED_TO_IDLE); } err = allocateBuffers(); if (err != (status_t)OK) { return err; } if (mQuirks & kRequiresLoadedToIdleAfterAllocation) { err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle); CHECK_EQ(err, (status_t)OK); setState(LOADED_TO_IDLE); } while (mState != EXECUTING && mState != ERROR) { mAsyncCompletion.wait(mLock); } return mState == ERROR ? UNKNOWN_ERROR : OK; }

    omxcodec有一些状态的换转,然后就是allocateBuffers这个数函了

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
{ if (mNativeWindow != NULL && portIndex == kPortIndexOutput) { return allocateOutputBuffersFromNativeWindow(); } if ((mFlags & kEnableGrallocUsageProtected) && portIndex == kPortIndexOutput) { ALOGE("protected output buffers must be stent to an ANativeWindow"); return PERMISSION_DENIED; } status_t err = OK; if ((mFlags & kStoreMetaDataInVideoBuffers) && portIndex == kPortIndexInput) { err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE); if (err != OK) { ALOGE("Storing meta data in video buffers is not supported"); return err; } } OMX_PARAM_PORTDEFINITIONTYPE def; InitOMXParams(&def); def.nPortIndex = portIndex; err = mOMX->getParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); if (err != OK) { return err; } size_t totalSize = def.nBufferCountActual * def.nBufferSize; mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec"); for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) { sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize); CHECK(mem.get() != NULL); BufferInfo info; info.mData = NULL; info.mSize = def.nBufferSize; IOMX::buffer_id buffer; if (portIndex == kPortIndexInput && ((mQuirks & kRequiresAllocateBufferOnInputPorts) || (mFlags & kUseSecureInputBuffers))) { if (mOMXLivesLocally) { mem.clear(); err = mOMX->allocateBuffer( mNode, portIndex, def.nBufferSize, &buffer, &info.mData); } else { err = mOMX->allocateBufferWithBackup( mNode, portIndex, mem, &buffer); } } else if (portIndex == kPortIndexOutput && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) { if (mOMXLivesLocally) { mem.clear(); err = mOMX->allocateBuffer( mNode, portIndex, def.nBufferSize, &buffer, &info.mData); } else { err = mOMX->allocateBufferWithBackup( mNode, portIndex, mem, &buffer); } } else { err = mOMX->useBuffer(mNode, portIndex, mem, &buffer); } if (err != OK) { ALOGE("allocate_buffer_with_backup failed"); return err; } if (mem != NULL) { info.mData = mem->pointer(); } info.mBuffer = buffer; info.mStatus = OWNED_BY_US; info.mMem = mem; info.mMediaBuffer = NULL; if (portIndex == kPortIndexOutput) { if (!(mOMXLivesLocally && (mQuirks & kRequiresAllocateBufferOnOutputPorts) && (mQuirks & kDefersOutputBufferAllocation))) { // If the node does not fill in the buffer ptr at this time, // we will defer creating the MediaBuffer until receiving // the first FILL_BUFFER_DONE notification instead. info.mMediaBuffer = new MediaBuffer(info.mData, info.mSize); info.mMediaBuffer->setObserver(this); } } mPortBuffers[portIndex].push(info); CODEC_LOGV("allocated buffer %p on %s port", buffer, portIndex == kPortIndexInput ? "input" : "output"); } if (portIndex == kPortIndexOutput) { sp<MetaData> meta = mSource->getFormat(); int32_t delay = 0; if (!meta->findInt32(kKeyEncoderDelay, &delay)) { delay = 0; } int32_t padding = 0; if (!meta->findInt32(kKeyEncoderPadding, &padding)) { padding = 0; } int32_t numchannels = 0; if (delay + padding) { if (mOutputFormat->findInt32(kKeyChannelCount, &numchannels)) { size_t frameSize = numchannels * sizeof(int16_t); if (mSkipCutBuffer != NULL) { size_t prevbuffersize = mSkipCutBuffer->size(); if (prevbuffersize != 0) { ALOGW("Replacing SkipCutBuffer holding %d bytes", prevbuffersize); } } mSkipCutBuffer = new SkipCutBuffer(delay * frameSize, padding * frameSize); } } } // dumpPortStatus(portIndex); if (portIndex == kPortIndexInput && (mFlags & kUseSecureInputBuffers)) { Vector<MediaBuffer *> buffers; for (size_t i = 0; i < def.nBufferCountActual; ++i) { const BufferInfo &info = mPortBuffers[kPortIndexInput].itemAt(i); MediaBuffer *mbuf = new MediaBuffer(info.mData, info.mSize); buffers.push(mbuf); } status_t err = mSource->setBuffers(buffers); if (err != OK) { for (size_t i = 0; i < def.nBufferCountActual; ++i) { buffers.editItemAt(i)->release(); } buffers.clear(); CODEC_LOGE( "Codec requested to use secure input buffers but " "upstream source didn't support that."); return err; } } return OK; }

    这个数函挺主要的,omx node是通过port来通信的,inport和output,入输node只有inport,而输出node就只有outport,间中码解的node就要需两个port

    先看inport的内存分配,有两个数函 allocatebuffer 和 usebuffer,如果不要需node重新分配内存,那就只要需用使application分配的内存,否则会在port面上重新分配内存

    为什么要需再port面上重新分配内存呢,多是DRM等原因虑考。

    在看一下outport的分配

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
{ // Get the number of buffers needed. OMX_PARAM_PORTDEFINITIONTYPE def; InitOMXParams(&def); def.nPortIndex = kPortIndexOutput; status_t err = mOMX->getParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); if (err != OK) { return err; } err = native_window_set_buffers_geometry( mNativeWindow.get(), def.format.video.nFrameWidth, def.format.video.nFrameHeight, def.format.video.eColorFormat); if (err != 0) { ALOGE("native_window_set_buffers_geometry failed: %s (%d)", strerror(-err), -err); return err; } initNativeWindowCrop(); err = applyRotation(); if (err != OK) { return err; } // Set up the native window. OMX_U32 usage = 0; err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage); if (err != 0) { ALOGW("querying usage flags from OMX IL component failed: %d", err); // XXX: Currently this error is logged, but not fatal. usage = 0; } if (mFlags & kEnableGrallocUsageProtected) { usage |= GRALLOC_USAGE_PROTECTED; } // Make sure to check whether either Stagefright or the video decoder // requested protected buffers. if (usage & GRALLOC_USAGE_PROTECTED) { // Verify that the ANativeWindow sends images directly to // SurfaceFlinger. int queuesToNativeWindow = 0; err = mNativeWindow->query( mNativeWindow.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, &queuesToNativeWindow); if (err != 0) { ALOGE("error authenticating native window: %d", err); return err; } if (queuesToNativeWindow != 1) { ALOGE("native window could not be authenticated"); return PERMISSION_DENIED; } } ALOGV("native_window_set_usage usage=0x%lx", usage); /* all commons */ usage |= (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP); ALOGV("native_window_set_usage usage=0x%lx", usage); err = native_window_set_usage( mNativeWindow.get(), usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP); if (err != 0) { ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err); return err; } int minUndequeuedBufs = 0; err = mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs); if (err != 0) { ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)", strerror(-err), -err); return err; } // XXX: Is this the right logic to use? It's not clear to me what the OMX // buffer counts refer to - how do they account for the renderer holding on // to buffers? if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) { OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs; def.nBufferCountActual = newBufferCount; err = mOMX->setParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); if (err != OK) { CODEC_LOGE("setting nBufferCountActual to %lu failed: %d", newBufferCount, err); return err; } } err = native_window_set_buffer_count( mNativeWindow.get(), def.nBufferCountActual); if (err != 0) { ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), -err); return err; } CODEC_LOGV("allocating %lu buffers from a native window of size %lu on " "output port", def.nBufferCountActual, def.nBufferSize); // Dequeue buffers and send them to OMX for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) { ANativeWindowBuffer* buf; err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf); if (err != 0) { ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err); break; } sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false)); BufferInfo info; info.mData = NULL; info.mSize = def.nBufferSize; info.mStatus = OWNED_BY_US; info.mMem = NULL; info.mMediaBuffer = new MediaBuffer(graphicBuffer); info.mMediaBuffer->setObserver(this); mPortBuffers[kPortIndexOutput].push(info); IOMX::buffer_id bufferId; err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer, &bufferId); if (err != 0) { CODEC_LOGE("registering GraphicBuffer with OMX IL component " "failed: %d", err); break; } mPortBuffers[kPortIndexOutput].editItemAt(i).mBuffer = bufferId; CODEC_LOGV("registered graphic buffer with ID %p (pointer = %p)", bufferId, graphicBuffer.get()); } OMX_U32 cancelStart; OMX_U32 cancelEnd; if (err != 0) { // If an error occurred while dequeuing we need to cancel any buffers // that were dequeued. cancelStart = 0; cancelEnd = mPortBuffers[kPortIndexOutput].size(); } else { // Return the last two buffers to the native window. cancelStart = def.nBufferCountActual - minUndequeuedBufs; cancelEnd = def.nBufferCountActual; } for (OMX_U32 i = cancelStart; i < cancelEnd; i++) { BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(i); cancelBufferToNativeWindow(info); } return err; }

    start的预备也做完了,主要是给port分配内存,基本也只是摘抄代码了

    start当前,就要kick off了,下篇开始播放了

    

    

文章结束给大家分享下程序员的一些笑话语录: IT业众生相
第一级:神人,天资过人而又是技术狂热者同时还拥有过人的商业头脑,高瞻远瞩,技术过人,大器也。如丁磊,求伯君。
第二级:高人,有天赋,技术过人但没有过人的商业头脑,通常此类人不是顶尖黑客就是技术总监之流。
第三级:牛人,技术精湛,熟悉行业知识,敢于创新,有自己的公司和软件产品。
第四级:工头,技术精湛,有领导团队的能力,此类人大公司项目经理居多。
第五级:技术工人,技术精湛,熟悉行业知识但领导能力欠加,此类人大多为系分人员或资深程序员,基本上桀骜不逊,自视清高,不愿于一般技术人员为伍,在论坛上基本以高手面目出现。
第六级:熟练工人,技术有广度无深度,喜欢钻研但浅尝辄止。此类人大多为老程序员,其中一部分喜欢利用工具去查找网上有漏洞的服务器,干点坏事以获取成绩感。如果心情好,在论坛上他们会回答菜鸟的大部分问题。此级别为软件业苦力的重要组成部分。
第七级:工人,某些技术较熟练但缺乏深度和广度,此类人大多为程序员级别,经常在论坛上提问偶尔也回答菜鸟的问题。为软件产业苦力的主要组成部分。
第八级:菜鸟,入门时间不长,在论坛上会反复提问很初级的问题,有一种唐僧的精神。虽然招人烦但基本很可爱。只要认真钻研,一两年后就能升级到上一层。
第九级:大忽悠,利用中国教育的弊病,顶着一顶高学历的帽子,在小公司里混个软件部经理,设计不行,代码不行,只会胡乱支配下属,拍领导马屁,在领导面前胡吹海侃,把自己打扮成技术高手的模样。把勾心斗角的办公室文化引入技术部门,实在龌龊!
第十级:驴或傻X,会写SELECT语句就说自己精通ORALCE,连寄存器有几种都不知道就说自己懂汇编,建议全部送到日本当IT产业工人,挣了日本人的钱还严重打击日本的软件业!

转载于:https://www.cnblogs.com/jiangu66/archive/2013/04/15/3023060.html

最后

以上就是认真芝麻最近收集整理的关于内存、分配-OMXCodec源码分析---part2-by小雨的全部内容,更多相关内存、分配-OMXCodec源码分析---part2-by小雨内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部