|
1 <?xml version="1.0" encoding="utf-8"?> |
|
2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. --> |
|
3 <!-- This component and the accompanying materials are made available under the terms of the License |
|
4 "Eclipse Public License v1.0" which accompanies this distribution, |
|
5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". --> |
|
6 <!-- Initial Contributors: |
|
7 Nokia Corporation - initial contribution. |
|
8 Contributors: |
|
9 --> |
|
10 <!DOCTYPE concept |
|
11 PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd"> |
|
12 <concept id="GUID-A578ECBB-28C5-51C6-A040-4AE65AD38C07" xml:lang="en"><title>Stream |
|
13 Encoding And Stream Decoding</title><prolog><metadata><keywords/></metadata></prolog><conbody> |
|
14 <p>This document gives you more information about the stream encoding and |
|
15 stream decoding method. </p> |
|
16 <section><title>Purpose</title> <p>This tutorial explains how to encode and |
|
17 decode an image by passing pixel data block by block. </p> <p><b>Required |
|
18 Background</b> </p> <p>The image is decoded / encoded using <filepath>imageconversion.dll</filepath> and |
|
19 currently only JPEG codec is supported for the streaming block method, so <filepath>jpegcodec.dll</filepath> is |
|
20 used from the Imaging Plugins component. </p> <p><b>Introduction</b> </p> <p>An image is compressed into an image frame. This |
|
21 is decoded / encoded in one go which consumes more memory usage. </p> <p>The |
|
22 Symbian <filepath>JPEG</filepath> codec now supports enhanced functionality |
|
23 during the encode / decode operation using Stream Encoding and Stream Decoding |
|
24 methods. In these methods an image frame which is part of a compressed image |
|
25 can be divided into sub blocks and these are encoded / decoded block by block |
|
26 of YUV pixel data. </p> <p>For decoder <xref href="GUID-7EC0A873-5ABA-3D11-880B-65466CBAA399.dita"><apiname>MImageConvStreamedDecode</apiname></xref> and <xref href="GUID-D4A1D719-6A38-39E2-9664-789CBABAC92E.dita"><apiname>TImageConvStreamedDecode</apiname></xref> are |
|
27 used to adapt the streaming functionality. And for encoder <xref href="GUID-D95B2E2D-CBE9-3838-86F5-EC0FBC03C6A6.dita"><apiname>MImageConvStreamedEncode</apiname></xref> and <xref href="GUID-653CA65B-13B7-3EFE-A25E-3EF8C41AABBB.dita"><apiname>TImageConvStreamedEncode</apiname></xref> are used to adapt the streaming functionality. </p> <p> <b>Note:- </b> Only |
|
28 the Symbian JPEG codec supports decoding / encoding of an image using Stream |
|
29 Encoding and Stream Decoding methods which consumes less memory usage. No |
|
30 other Symbian codecs are modified to provide this support. </p> <p>The Stream |
|
31 Encoding And Stream Decoding methods also supports cropping or scaling an |
|
32 image in sequence order or random order. </p> <p><b>Setup |
|
33 and Configuration Requirements</b> </p> <p>For the encoder / the decoder to |
|
34 perform streaming you need to set up the navigation mode by using the streaming |
|
35 capabilities. </p> <ul> |
|
36 <li id="GUID-1936B31A-8043-5401-9D7F-4F2BCFE26B9A"><p>The |
|
37 streaming capabilities for decoding are supported by the <xref href="GUID-0EBD074D-49E9-5E3E-9FA9-3484E968ABDB.dita#GUID-0EBD074D-49E9-5E3E-9FA9-3484E968ABDB/GUID-A5E7656C-6537-5D06-B81B-119614B73DB9">Image Processor Adaptation Plug-in</xref> decoder. For example you can obtain |
|
38 the optimum number of blocks through streaming in a single request to get |
|
39 maximum performance by using the parameter <codeph>aOptimalBlocksPerRequest</codeph>. </p> </li> |
|
40 <li/> |
|
41 <li id="GUID-CF5BEF30-BE94-5982-A816-522323FE6C0B"><p>The streaming capabilities |
|
42 for encoding are supported by the <xref href="GUID-0EBD074D-49E9-5E3E-9FA9-3484E968ABDB.dita#GUID-0EBD074D-49E9-5E3E-9FA9-3484E968ABDB/GUID-A5E7656C-6537-5D06-B81B-119614B73DB9">Image |
|
43 Processor Adaptation Plug-in</xref> encoder. For example you can obtain the |
|
44 maximum number of blocks through streaming by using the parameter <codeph>aMaxBlocksPerRequest</codeph>. </p> </li> |
|
45 </ul> <p>During the decode operation, the blocks or sub-frames can be navigated |
|
46 in the following order : </p> <ul> |
|
47 <li id="GUID-CB2510A3-8BF8-5A13-8BB1-9B9820D9B584"><p>The sub-frames or blocks |
|
48 can be passed sequentially from top left of the image, left to right and top |
|
49 to bottom. </p> </li> |
|
50 <li id="GUID-DF38C7D7-DA96-5A42-999B-6A6FC5BB218B"><p>The blocks can be passed |
|
51 in random order to access each block. </p> </li> |
|
52 </ul> <p>During the encode operation,the blocks or sub-frames can be navigated |
|
53 : </p> <ul> |
|
54 <li id="GUID-23349B8D-C81D-5550-A49C-A50AE231AB7A"><p>Sequentially from top |
|
55 left of the image, left to right and top to bottom. </p> </li> |
|
56 <li id="GUID-74F35DB8-90A3-52DA-A207-B3519D25F925"><p>Randomly from top of |
|
57 the image to bottom and bottom of the image to top. </p> </li> |
|
58 </ul> </section> |
|
59 <section><title>Using Stream Encoding And Stream Decoding </title> <p>The |
|
60 Following tasks are covered in this tutorial: </p> <ul> |
|
61 <li id="GUID-BF113946-4EA4-5076-A88F-DC177873030F"><p><xref href="GUID-A578ECBB-28C5-51C6-A040-4AE65AD38C07.dita#GUID-A578ECBB-28C5-51C6-A040-4AE65AD38C07/GUID-FE6502E4-30C6-5E9F-A3A4-537352065026">How to encode and decode an image by the streaming block method</xref> </p> </li> |
|
62 </ul> <p id="GUID-FE6502E4-30C6-5E9F-A3A4-537352065026"><b>Basic Procedure For Stream |
|
63 Encoding And Stream Decoding</b> </p> <p>The high level steps to perform streaming |
|
64 block during encode and decode operation are as follows: </p> <ol id="GUID-151BD6BB-9028-5DA0-B616-E93F3C328311"> |
|
65 <li id="GUID-BFCC59BD-C76A-5AEF-AED7-CAD35E7171C4"><p>To create the encoder |
|
66 call <xref href="GUID-737DA130-9A66-39E2-9E68-2E65F37E02C8.dita#GUID-737DA130-9A66-39E2-9E68-2E65F37E02C8/GUID-1F25CC18-A8E4-3E1D-BA3D-F5F472E20CC0"><apiname>CImageEncoder::FileNewL()</apiname></xref> or <xref href="GUID-737DA130-9A66-39E2-9E68-2E65F37E02C8.dita#GUID-737DA130-9A66-39E2-9E68-2E65F37E02C8/GUID-51ECB4D3-5A87-35E7-82EB-DF2BAEAB2CAC"><apiname>CImageEncoder::DataNewL()</apiname></xref> and |
|
67 to create the decoder call <xref href="GUID-8F2953B2-E64E-3D8B-B30B-B35B373368D4.dita#GUID-8F2953B2-E64E-3D8B-B30B-B35B373368D4/GUID-6DA07559-7DDC-32A9-9E09-D557348D46DE"><apiname>CImageDecoder::FileNewL()</apiname></xref> or <xref href="GUID-8F2953B2-E64E-3D8B-B30B-B35B373368D4.dita#GUID-8F2953B2-E64E-3D8B-B30B-B35B373368D4/GUID-00FB83E8-3759-32BE-B6E8-6F04EC60A909"><apiname>CImageDecoder::DataNewL()</apiname></xref>. </p> </li> |
|
68 <li id="GUID-7D610B86-BF34-5772-B901-3582CD7A600D"><p>For the encoder streaming, |
|
69 requests a streaming interface through <xref href="GUID-737DA130-9A66-39E2-9E68-2E65F37E02C8.dita#GUID-737DA130-9A66-39E2-9E68-2E65F37E02C8/GUID-452047D4-E3A8-3200-9F10-697FF5200BB3"><apiname>CImageEncoder::BlockStreamerL()</apiname></xref> and |
|
70 for the decoder streaming, request an interface through <xref href="GUID-8F2953B2-E64E-3D8B-B30B-B35B373368D4.dita#GUID-8F2953B2-E64E-3D8B-B30B-B35B373368D4/GUID-14A53DAA-DFCE-347F-AFC5-4C0F9FE3081F"><apiname>CImageDecoder::BlockStreamerL()</apiname></xref>. </p> <p>After |
|
71 requesting the streaming interface, if the streaming extension is supported |
|
72 then a T class pointer is returned which gives access to the JPEG codec extension. <xref href="GUID-D4A1D719-6A38-39E2-9664-789CBABAC92E.dita"><apiname>TImageConvStreamedDecode</apiname></xref> gives |
|
73 the extension functionality for stream decoding and <xref href="GUID-653CA65B-13B7-3EFE-A25E-3EF8C41AABBB.dita"><apiname>TImageConvStreamedEncode</apiname></xref> gives |
|
74 the extension functionality for stream encoding. </p> </li> |
|
75 <li id="GUID-1517FF6C-4F5E-55FD-A71F-18A200616BB5"><p>To |
|
76 set the navigation mode for the encode streaming call the Image Processor |
|
77 Adaptation Plug-in encoder navigator and for the decode streaming call the |
|
78 Image Processor Adaptation Plug-in decoder navigator. </p> <p>For |
|
79 decode streaming, the navigation possibilities are : </p> <ul> |
|
80 <li id="GUID-910F6950-4355-5989-BA29-1319EEFF26B0"><p>The blocks are returned |
|
81 from first to last. </p> </li> |
|
82 <li id="GUID-B5E34D8E-8DBD-5D63-AF5A-4D88E57BA6F2"><p>The blocks are returned |
|
83 from last to first. </p> </li> |
|
84 <li id="GUID-421A8EA9-FE99-59AB-BED7-4051DD798120"><p>The blocks are returned |
|
85 randomly e.g. 18, 5, 20. </p> </li> |
|
86 <li id="GUID-C1AD41C6-FD4D-5602-875F-A14F4778866F"><p>The blocks are returned |
|
87 in a random order but moving only from first to last e.g. 1, 5, 18. </p> </li> |
|
88 <li id="GUID-B0D25618-B77B-5F63-AF7D-8DC0B39277AC"><p>The blocks are returned |
|
89 in a random order but moving only from last to first e.g. 18, 5, 1. </p> </li> |
|
90 </ul> <p>The navigation are shown below: </p> <codeblock id="GUID-88CF01B6-2F4B-57C9-A30D-4651DB32496E" xml:space="preserve"> |
|
91 |
|
92 enum TNavigation |
|
93 { |
|
94 |
|
95 ENavigationSequentialForward = 0x01, // Sequential order from first to last |
|
96 ENavigationSequentialBackwards = 0x10, // Sequential order from last to first |
|
97 ENavigationRandom = 0x08, // random order |
|
98 ENavigationRandomForward = 0x02, // random order frist to last |
|
99 ENavigationRandomBackwards = 0x04, // random order last to first |
|
100 |
|
101 } |
|
102 |
|
103 </codeblock> <p>For encode streaming, the navigation possibilities are: </p> <ul> |
|
104 <li id="GUID-EC70F523-E8BE-5FC9-8B52-7550685FB77A"><p>The blocks are returned |
|
105 from first to last. </p> </li> |
|
106 <li id="GUID-7076D2D9-C438-5A56-9220-98C26D0D5D5C"><p>The blocks are returned |
|
107 in a random order but moving only from first to last e.g. 1, 5, 18. </p> </li> |
|
108 <li id="GUID-6E1049DC-165F-5B49-A2A9-7C0879E9F6AB"><p>The blocks are returned |
|
109 in a random order but moving only from last to first e.g. 1, 5, 18. </p> </li> |
|
110 </ul> <codeblock id="GUID-68FCCD3B-0616-584C-AB88-84F4F68732B2" xml:space="preserve"> |
|
111 |
|
112 enum TNavigation |
|
113 { |
|
114 |
|
115 ENavigationSequentialForward = 0x01, // sequential order from first to last |
|
116 ENavigationRandomForward = 0x02, // random order from first to last |
|
117 EnavigationRandomBackwards = 0x04, // random order from last to first |
|
118 |
|
119 }; |
|
120 |
|
121 </codeblock> </li> |
|
122 <li id="GUID-731867F0-3873-51BD-8CB6-6E549B1802F4"><p>To initialize the stream |
|
123 decoder use <xref href="GUID-D4A1D719-6A38-39E2-9664-789CBABAC92E.dita#GUID-D4A1D719-6A38-39E2-9664-789CBABAC92E/GUID-3DDDDAB5-DDF7-3904-BA67-B66FBBD19DCF"><apiname>TImageConvStreamedDecode::InitFrameL()</apiname></xref> and |
|
124 use its parameter. </p> </li> |
|
125 <li id="GUID-E3231926-0292-5A3D-88C5-47E798818294"><p>To initialize the encode |
|
126 streaming use <xref href="GUID-653CA65B-13B7-3EFE-A25E-3EF8C41AABBB.dita#GUID-653CA65B-13B7-3EFE-A25E-3EF8C41AABBB/GUID-C98EF919-247F-37EE-A10A-091441C940B9"><apiname>TImageConvStreamedEncode::InitFrameL()</apiname></xref> and |
|
127 use its parameter. </p> </li> |
|
128 <li id="GUID-91DAA7B8-9437-5F8C-9628-CA562080A923"><p>During decode function, |
|
129 the memory for storing <xref href="GUID-54159F7E-C9A9-3FB5-806D-751DAF213290.dita"><apiname>CImageFrame</apiname></xref> must be large enough |
|
130 to contain the decoded frame. To obtain the buffer size for a particular decode |
|
131 function call <xref href="GUID-D4A1D719-6A38-39E2-9664-789CBABAC92E.dita#GUID-D4A1D719-6A38-39E2-9664-789CBABAC92E/GUID-8DF0A327-AD84-3E66-939C-042BC266A8A5"><apiname>TImageConvStreamedDecode::GetBufferSize()</apiname></xref>. </p> <p>The <codeph>GetBufferSize()</codeph> function |
|
132 returns: </p> <ul> |
|
133 <li id="GUID-9A3EA468-28C5-592B-AAE6-FEA02E2B37A4"><p>The required size to |
|
134 store the image when using the Imaging plugins format code. </p> </li> |
|
135 <li id="GUID-91AC139C-7E44-50FC-8AEB-7BA7ADCF4AAD"><p>The size in pixels of |
|
136 the block from the stream are returned by calling <codeph> aBlockSizeInPixels</codeph>, |
|
137 when <codeph>aNumBlocks</codeph> of minimum block size are requested. </p> </li> |
|
138 </ul> </li> |
|
139 <li id="GUID-BE2118E1-0E23-5309-B4E1-7490BC228B2D"><p>To store the image data |
|
140 in any format or layout which is described by a format code UID, create an |
|
141 empty image frame using <xref href="GUID-54159F7E-C9A9-3FB5-806D-751DAF213290.dita"><apiname>CImageFrame</apiname></xref>. </p> </li> |
|
142 <li id="GUID-9B0A1F73-D1FA-543F-AA9A-96FFA8CE0225"><p>To set the image frame |
|
143 size in pixels call <xref href="GUID-54159F7E-C9A9-3FB5-806D-751DAF213290.dita#GUID-54159F7E-C9A9-3FB5-806D-751DAF213290/GUID-BC2B18A5-0C3C-388B-A613-80D623F26F08"><apiname>CImageFrame::SetFrameSizeInPixels()</apiname></xref>. |
|
144 The parameter <codeph>aFrameSize</codeph> is used to returned <codeph>aBlockSizeInPixels</codeph> from <codeph>GetBufferSize</codeph>. </p> </li> |
|
145 <li id="GUID-9F9887F0-D93F-54C7-8476-D2AC6413F4BE"><p>In decode streaming, |
|
146 in order to start asynchronous call to return blocks use <xref href="GUID-7EC0A873-5ABA-3D11-880B-65466CBAA399.dita#GUID-7EC0A873-5ABA-3D11-880B-65466CBAA399/GUID-92A9FB31-2B0D-305D-A8A2-04B63C2861CB"><apiname>MImageConvStreamedDecode::GetNextBlocks()</apiname></xref>. </p> </li> |
|
147 <li id="GUID-54FF23F9-5A7F-55B5-9AE3-599E78F755CB"><p>In encode streaming, |
|
148 in order to start asynchronous call to append blocks use <xref href="GUID-D95B2E2D-CBE9-3838-86F5-EC0FBC03C6A6.dita#GUID-D95B2E2D-CBE9-3838-86F5-EC0FBC03C6A6/GUID-F3618D7A-94C4-3259-AFBD-1E83C222765C"><apiname>MImageConvStreamedEncode::AppendBlocks()</apiname></xref>. </p> </li> |
|
149 </ol> <p> <b>Note:</b> The memory optimization is mainly achieved by <codeph>GetNextBlocks</codeph> and <codeph>AppendBlocks</codeph> applying |
|
150 effect to the image frame block. And the streaming is only supported by the |
|
151 images which are multiples of Minimum Coded Unit (MCU). </p> <p><b>Example </b> </p> <p>The example below shows how to use stream encoding |
|
152 and stream decoding methods: </p> <codeblock id="GUID-985CFE87-9321-5C4F-A112-B8A722DC35FE" xml:space="preserve"> |
|
153 |
|
154 void CIclExample::StreamDecodeAndEncodeYuvFrameL(const TDesC& aSrcFileName, const TDesC& aDestFileName) |
|
155 { |
|
156 const TInt KFrameNumber = 0; // first frame |
|
157 const TUid KFormat = KUidFormatYUV422Interleaved; // 422 sampling scheme |
|
158 const TInt KNumBlocksToGet = 1; |
|
159 RChunk chunk; |
|
160 TSize streamBlockSizeInPixels; |
|
161 TEncodeStreamImgProcPlugin ImgProcPlugin; |
|
162 TInt numBlocksRead = 0; |
|
163 TBool haveMoreBlocks = ETrue; |
|
164 // Create the decoder, passing the filename. The image is recognised by the |
|
165 // Image Conversion Library, an appropriate codec plugin loaded and the image headers parsed. |
|
166 // If the image is not recognised or valid then the call will leave with an error |
|
167 CImageDecoder* jpegImageDecoder = static_cast<CJPEGImageFrameDecoder*>( CImageDecoder::FileNewL(iFs, aSrcFileName)); |
|
168 CleanupStack::PushL(jpegImageDecoder); |
|
169 |
|
170 // Create the encoder, passing the filename. The image is recognised by the |
|
171 // Image Conversion Library, an appropriate codec plugin loaded and the image headers parsed. |
|
172 // If the image is not recognised or valid then the call will leave with an error |
|
173 CImageEncoder* jpegImageEncoder = static_cast<CJPEGImageFrameEncoder*>( CImageEncoder::FileNewL(iFs, aDestFileName, CImageEncoder::EOptionNone, KImageTypeJPGUid)); |
|
174 CleanupStack::PushL(jpegImageEncoder); |
|
175 |
|
176 // Create encode & decode Block Streamer |
|
177 TImageConvStreamedDecode* streamDecode = jpegImageDecoder->BlockStreamerL(); |
|
178 TImageConvStreamedEncode* streamEncode = jpegImageEncoder->BlockStreamerL(); |
|
179 |
|
180 TFrameInfo frameInfo = jpegImageDecoder->FrameInfo(); |
|
181 TSize frameSizeInPixels(frameInfo.iOverallSizeInPixels); //NOTE: The image used for decoding should be multiple of MCU(Minimum coded unit) |
|
182 |
|
183 //set the navigation mode initialize decoder frame |
|
184 TDecodeStreamImgProcPlugin::TNavigation decodeNavigation = TDecodeStreamImgProcPlugin::ENavigationSequentialForward; |
|
185 streamDecode->InitFrameL(KFormat, KFrameNumber, decodeNavigation); |
|
186 |
|
187 streamEncode->GetCapabilities(KFormat,ImgProcPlugin); |
|
188 TSize blockSizeInPixels = TSize(ImgProcPlugin.MinBlockSizeInPixels()); |
|
189 |
|
190 //initialize encoder frameImgProcPlugin::ENavigationSequentialForward; |
|
191 streamEncode->InitFrameL(KFormat, KFrameNumber, frameSizeInPixels, blockSizeInPixels, encodeNavigation, NULL); |
|
192 |
|
193 //When decoding, the buffer wrapped by the destination CImageFrame must be large enough to contain the decoded frame. |
|
194 //GetBufferSize() should be used to obtain the buffer size required for a particular decode |
|
195 TInt imageSizeInBytes = streamDecode->GetBufferSize(KFormat, streamBlockSizeInPixels, KNumBlocksToGet); |
|
196 |
|
197 User::LeaveIfError(chunk.CreateGlobal(KRChunk, imageSizeInBytes, imageSizeInBytes, EOwnerProcess)); |
|
198 CleanupClosePushL(chunk); |
|
199 |
|
200 // Create an empty imageframe |
|
201 CImageFrame* imageFrame = CImageFrame::NewL(&chunk, imageSizeInBytes, 0); |
|
202 CleanupStack::PushL(imageFrame); |
|
203 |
|
204 imageFrame->SetFrameSizeInPixels(streamBlockSizeInPixels); |
|
205 |
|
206 while(haveMoreBlocks) |
|
207 { |
|
208 // See Note 1 |
|
209 CActiveListener* activeListener = CreateAndInitializeActiveListenerLC(); |
|
210 |
|
211 //decoder get blocks |
|
212 streamDecode->GetNextBlocks(activeListener->iStatus, *imageFrame, KNumBlocksToGet, numBlocksRead, haveMoreBlocks); |
|
213 |
|
214 // See Note 2 |
|
215 CActiveScheduler::Start(); |
|
216 User::LeaveIfError(activeListener->iStatus.Int()); // decode complete. |
|
217 |
|
218 //NOTE: Apply effects like adjust brightness etc in low memory conditions by use of streaming to the image frame block |
|
219 |
|
220 // See Note 1 |
|
221 activeListener->InitializeActiveListener(); |
|
222 |
|
223 //encoder append blocks |
|
224 streamEncode->AppendBlocks(activeListener->iStatus, *imageFrame, numBlocksRead); |
|
225 |
|
226 // See Note 2 |
|
227 CActiveScheduler::Start(); |
|
228 User::LeaveIfError(activeListener->iStatus.Int()); // encode complete. |
|
229 |
|
230 CleanupStack::PopAndDestroy(activeListener); // encodeActiveListener |
|
231 } |
|
232 |
|
233 CleanupStack::PopAndDestroy(4); // imageFrame, chunk, jpegImageEncoder and jpegImageDecoder |
|
234 } |
|
235 </codeblock> </section> |
|
236 </conbody><related-links> |
|
237 <link href="GUID-88091838-03FC-550F-9A3D-DA70907EF955.dita"><linktext>Imaging Frameworks |
|
238 overview</linktext></link> |
|
239 <link href="GUID-3D9C4B45-EEA0-581C-A9E5-8B2535014930.dita"><linktext>Image Conversion |
|
240 Overview</linktext></link> |
|
241 <link href="GUID-6DC34798-86CE-537D-B3B8-9A94FF77B283.dita"><linktext>Image Encoding |
|
242 Tutorial</linktext></link> |
|
243 <link href="GUID-B10B048F-37FF-53E7-92B9-83F8C197566A.dita"><linktext>Image Decoding |
|
244 Tutorial</linktext></link> |
|
245 <link href="GUID-A825B62E-B5F6-5FDD-B267-E47103D57FD8.dita"><linktext>Guide to |
|
246 Symbian supplied Codecs </linktext></link> |
|
247 </related-links></concept> |