Symbian3/SDK/Source/GUID-A578ECBB-28C5-51C6-A040-4AE65AD38C07.dita
author Dominic Pinkman <dominic.pinkman@nokia.com>
Tue, 20 Jul 2010 12:00:49 +0100
changeset 13 48780e181b38
parent 0 89d6a7a84779
permissions -rw-r--r--
Week 28 contribution of SDK documentation content. See release notes for details. Fixes bugs Bug 1897 and Bug 1522.

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License 
"Eclipse Public License v1.0" which accompanies this distribution, 
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
    Nokia Corporation - initial contribution.
Contributors: 
-->
<!DOCTYPE concept
  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="GUID-A578ECBB-28C5-51C6-A040-4AE65AD38C07" xml:lang="en"><title>Stream
Encoding And Stream Decoding</title><prolog><metadata><keywords/></metadata></prolog><conbody>
<p>This document gives you more information about the stream encoding and
stream decoding method. </p>
<section><title>Purpose</title> <p>This tutorial explains how to encode and
decode an image by passing pixel data block by block. </p> <p><b>Required
Background</b> </p> <p>The image is decoded / encoded using <filepath>imageconversion.dll</filepath> and
currently only JPEG codec is supported for the streaming block method, so <filepath>jpegcodec.dll</filepath> is
used from the Imaging Plugins component. </p> <p><b>Introduction</b> </p> <p>An image is compressed into an image frame. This
is decoded / encoded in one go which consumes more memory usage. </p> <p>The
Symbian <filepath>JPEG</filepath> codec now supports enhanced functionality
during the encode / decode operation using Stream Encoding and Stream Decoding
methods. In these methods an image frame which is part of a compressed image
can be divided into sub blocks and these are encoded / decoded block by block
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
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
the Symbian JPEG codec supports decoding / encoding of an image using Stream
Encoding and Stream Decoding methods which consumes less memory usage. No
other Symbian codecs are modified to provide this support. </p> <p>The Stream
Encoding And Stream Decoding methods also supports cropping or scaling an
image in sequence order or random order. </p> <p><b>Setup
and Configuration Requirements</b> </p> <p>For the encoder / the decoder to
perform streaming you need to set up the navigation mode by using the streaming
capabilities. </p> <ul>
<li id="GUID-1936B31A-8043-5401-9D7F-4F2BCFE26B9A"><p>The
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
the optimum number of blocks through streaming in a single request to get
maximum performance by using the parameter <codeph>aOptimalBlocksPerRequest</codeph>. </p> </li>
<li/>
<li id="GUID-CF5BEF30-BE94-5982-A816-522323FE6C0B"><p>The streaming capabilities
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
Processor Adaptation Plug-in</xref> encoder. For example you can obtain the
maximum number of blocks through streaming by using the parameter <codeph>aMaxBlocksPerRequest</codeph>. </p> </li>
</ul> <p>During the decode operation, the blocks or sub-frames can be navigated
in the following order : </p> <ul>
<li id="GUID-CB2510A3-8BF8-5A13-8BB1-9B9820D9B584"><p>The sub-frames or blocks
can be passed sequentially from top left of the image, left to right and top
to bottom. </p> </li>
<li id="GUID-DF38C7D7-DA96-5A42-999B-6A6FC5BB218B"><p>The blocks can be passed
in random order to access each block. </p> </li>
</ul> <p>During the encode operation,the blocks or sub-frames can be navigated
: </p> <ul>
<li id="GUID-23349B8D-C81D-5550-A49C-A50AE231AB7A"><p>Sequentially from top
left of the image, left to right and top to bottom. </p> </li>
<li id="GUID-74F35DB8-90A3-52DA-A207-B3519D25F925"><p>Randomly from top of
the image to bottom and bottom of the image to top. </p> </li>
</ul> </section>
<section><title>Using Stream Encoding And Stream Decoding </title> <p>The
Following tasks are covered in this tutorial: </p> <ul>
<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>
</ul> <p id="GUID-FE6502E4-30C6-5E9F-A3A4-537352065026"><b>Basic Procedure For Stream
Encoding And Stream Decoding</b> </p> <p>The high level steps to perform streaming
block during encode and decode operation are as follows: </p> <ol id="GUID-151BD6BB-9028-5DA0-B616-E93F3C328311">
<li id="GUID-BFCC59BD-C76A-5AEF-AED7-CAD35E7171C4"><p>To create the encoder
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
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>
<li id="GUID-7D610B86-BF34-5772-B901-3582CD7A600D"><p>For the encoder streaming,
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
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
requesting the streaming interface, if the streaming extension is supported
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
the extension functionality for stream decoding and <xref href="GUID-653CA65B-13B7-3EFE-A25E-3EF8C41AABBB.dita"><apiname>TImageConvStreamedEncode</apiname></xref> gives
the extension functionality for stream encoding. </p> </li>
<li id="GUID-1517FF6C-4F5E-55FD-A71F-18A200616BB5"><p>To
set the navigation mode for the encode streaming call the Image Processor
Adaptation Plug-in encoder navigator and for the decode streaming call the
Image Processor Adaptation Plug-in decoder navigator. </p> <p>For
decode streaming, the navigation possibilities are : </p> <ul>
<li id="GUID-910F6950-4355-5989-BA29-1319EEFF26B0"><p>The blocks are returned
from first to last. </p> </li>
<li id="GUID-B5E34D8E-8DBD-5D63-AF5A-4D88E57BA6F2"><p>The blocks are returned
from last to first. </p> </li>
<li id="GUID-421A8EA9-FE99-59AB-BED7-4051DD798120"><p>The blocks are returned
randomly e.g. 18, 5, 20. </p> </li>
<li id="GUID-C1AD41C6-FD4D-5602-875F-A14F4778866F"><p>The blocks are returned
in a random order but moving only from first to last e.g. 1, 5, 18. </p> </li>
<li id="GUID-B0D25618-B77B-5F63-AF7D-8DC0B39277AC"><p>The blocks are returned
in a random order but moving only from last to first e.g. 18, 5, 1. </p> </li>
</ul> <p>The navigation are shown below: </p> <codeblock id="GUID-88CF01B6-2F4B-57C9-A30D-4651DB32496E" xml:space="preserve">

enum TNavigation
        {
    
        ENavigationSequentialForward = 0x01, // Sequential order from first to last
  ENavigationSequentialBackwards = 0x10, // Sequential order from last to first
  ENavigationRandom = 0x08, // random order
        ENavigationRandomForward     = 0x02, // random order frist to last
        ENavigationRandomBackwards   = 0x04, // random order last to first
        
        }

</codeblock> <p>For encode streaming, the navigation possibilities are: </p> <ul>
<li id="GUID-EC70F523-E8BE-5FC9-8B52-7550685FB77A"><p>The blocks are returned
from first to last. </p> </li>
<li id="GUID-7076D2D9-C438-5A56-9220-98C26D0D5D5C"><p>The blocks are returned
in a random order but moving only from first to last e.g. 1, 5, 18. </p> </li>
<li id="GUID-6E1049DC-165F-5B49-A2A9-7C0879E9F6AB"><p>The blocks are returned
in a random order but moving only from last to first e.g. 1, 5, 18. </p> </li>
</ul> <codeblock id="GUID-68FCCD3B-0616-584C-AB88-84F4F68732B2" xml:space="preserve">

enum TNavigation
        {
    
        ENavigationSequentialForward = 0x01, // sequential order from first to last        
        ENavigationRandomForward     = 0x02, // random order from first to last    
        EnavigationRandomBackwards   = 0x04, // random order from last to first     
        
  };

</codeblock> </li>
<li id="GUID-731867F0-3873-51BD-8CB6-6E549B1802F4"><p>To initialize the stream
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
use its parameter. </p> </li>
<li id="GUID-E3231926-0292-5A3D-88C5-47E798818294"><p>To initialize the encode
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
use its parameter. </p> </li>
<li id="GUID-91DAA7B8-9437-5F8C-9628-CA562080A923"><p>During decode function,
the memory for storing <xref href="GUID-54159F7E-C9A9-3FB5-806D-751DAF213290.dita"><apiname>CImageFrame</apiname></xref> must be large enough
to contain the decoded frame. To obtain the buffer size for a particular decode
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
returns: </p> <ul>
<li id="GUID-9A3EA468-28C5-592B-AAE6-FEA02E2B37A4"><p>The required size to
store the image when using the Imaging plugins format code. </p> </li>
<li id="GUID-91AC139C-7E44-50FC-8AEB-7BA7ADCF4AAD"><p>The size in pixels of
the block from the stream are returned by calling <codeph> aBlockSizeInPixels</codeph>,
when <codeph>aNumBlocks</codeph> of minimum block size are requested. </p> </li>
</ul> </li>
<li id="GUID-BE2118E1-0E23-5309-B4E1-7490BC228B2D"><p>To store the image data
in any format or layout which is described by a format code UID, create an
empty image frame using <xref href="GUID-54159F7E-C9A9-3FB5-806D-751DAF213290.dita"><apiname>CImageFrame</apiname></xref>. </p> </li>
<li id="GUID-9B0A1F73-D1FA-543F-AA9A-96FFA8CE0225"><p>To set the image frame
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>.
The parameter <codeph>aFrameSize</codeph> is used to returned <codeph>aBlockSizeInPixels</codeph> from <codeph>GetBufferSize</codeph>. </p> </li>
<li id="GUID-9F9887F0-D93F-54C7-8476-D2AC6413F4BE"><p>In decode streaming,
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>
<li id="GUID-54FF23F9-5A7F-55B5-9AE3-599E78F755CB"><p>In encode streaming,
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>
</ol> <p> <b>Note:</b> The memory optimization is mainly achieved by <codeph>GetNextBlocks</codeph> and <codeph>AppendBlocks</codeph> applying
effect to the image frame block. And the streaming is only supported by the
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
and stream decoding methods: </p> <codeblock id="GUID-985CFE87-9321-5C4F-A112-B8A722DC35FE" xml:space="preserve">

void CIclExample::StreamDecodeAndEncodeYuvFrameL(const TDesC&amp; aSrcFileName, const TDesC&amp; aDestFileName)
    {
    const TInt KFrameNumber = 0; // first frame
    const TUid KFormat = KUidFormatYUV422Interleaved; // 422 sampling scheme
    const TInt KNumBlocksToGet = 1;
    RChunk chunk;
    TSize streamBlockSizeInPixels;
    TEncodeStreamImgProcPlugin ImgProcPlugin;
    TInt numBlocksRead = 0;
    TBool haveMoreBlocks = ETrue;
    // Create the decoder, passing the filename. The image is recognised by the 
    // Image Conversion Library, an appropriate codec plugin loaded and the image headers parsed.
    // If the image is not recognised or valid then the call will leave with an error
    CImageDecoder* jpegImageDecoder = static_cast&lt;CJPEGImageFrameDecoder*&gt;( CImageDecoder::FileNewL(iFs, aSrcFileName));
    CleanupStack::PushL(jpegImageDecoder);

    // Create the encoder, passing the filename. The image is recognised by the 
    // Image Conversion Library, an appropriate codec plugin loaded and the image headers parsed.
    // If the image is not recognised or valid then the call will leave with an error    
    CImageEncoder* jpegImageEncoder = static_cast&lt;CJPEGImageFrameEncoder*&gt;( CImageEncoder::FileNewL(iFs, aDestFileName, CImageEncoder::EOptionNone, KImageTypeJPGUid));
    CleanupStack::PushL(jpegImageEncoder);
    
    // Create encode &amp; decode Block Streamer
    TImageConvStreamedDecode* streamDecode = jpegImageDecoder-&gt;BlockStreamerL();    
    TImageConvStreamedEncode* streamEncode = jpegImageEncoder-&gt;BlockStreamerL();
    
    TFrameInfo frameInfo = jpegImageDecoder-&gt;FrameInfo();
    TSize frameSizeInPixels(frameInfo.iOverallSizeInPixels); //NOTE: The image used for decoding should be multiple of MCU(Minimum coded unit)
    
    //set the navigation mode initialize decoder frame
    TDecodeStreamImgProcPlugin::TNavigation decodeNavigation = TDecodeStreamImgProcPlugin::ENavigationSequentialForward;
    streamDecode-&gt;InitFrameL(KFormat, KFrameNumber, decodeNavigation);
    
    streamEncode-&gt;GetCapabilities(KFormat,ImgProcPlugin);
    TSize blockSizeInPixels = TSize(ImgProcPlugin.MinBlockSizeInPixels());
    
    //initialize encoder frameImgProcPlugin::ENavigationSequentialForward;
    streamEncode-&gt;InitFrameL(KFormat, KFrameNumber, frameSizeInPixels, blockSizeInPixels, encodeNavigation, NULL);

    //When decoding, the buffer wrapped by the destination CImageFrame must be large enough to contain the decoded frame.
    //GetBufferSize() should be used to obtain the buffer size required for a particular decode
    TInt imageSizeInBytes = streamDecode-&gt;GetBufferSize(KFormat, streamBlockSizeInPixels, KNumBlocksToGet);
            
    User::LeaveIfError(chunk.CreateGlobal(KRChunk, imageSizeInBytes, imageSizeInBytes, EOwnerProcess));    
    CleanupClosePushL(chunk);
        
    // Create an empty imageframe   
    CImageFrame* imageFrame = CImageFrame::NewL(&amp;chunk, imageSizeInBytes, 0);
    CleanupStack::PushL(imageFrame);

    imageFrame-&gt;SetFrameSizeInPixels(streamBlockSizeInPixels);
    
    while(haveMoreBlocks)
        {
        // See Note 1
        CActiveListener* activeListener = CreateAndInitializeActiveListenerLC();
        
        //decoder get blocks
        streamDecode-&gt;GetNextBlocks(activeListener-&gt;iStatus, *imageFrame, KNumBlocksToGet, numBlocksRead, haveMoreBlocks);
        
        // See Note 2
        CActiveScheduler::Start();
        User::LeaveIfError(activeListener-&gt;iStatus.Int()); // decode complete.
        
        //NOTE: Apply effects like adjust brightness etc in low memory conditions by use of streaming to the image frame block
                
        // See Note 1
        activeListener-&gt;InitializeActiveListener();
        
        //encoder append blocks
        streamEncode-&gt;AppendBlocks(activeListener-&gt;iStatus, *imageFrame, numBlocksRead);

        // See Note 2
        CActiveScheduler::Start();
        User::LeaveIfError(activeListener-&gt;iStatus.Int()); // encode complete.
        
        CleanupStack::PopAndDestroy(activeListener); // encodeActiveListener 
        }
    
    CleanupStack::PopAndDestroy(4); // imageFrame, chunk, jpegImageEncoder and jpegImageDecoder
    }
</codeblock> </section>
</conbody><related-links>
<link href="GUID-88091838-03FC-550F-9A3D-DA70907EF955.dita"><linktext>Imaging Frameworks
overview</linktext></link>
<link href="GUID-3D9C4B45-EEA0-581C-A9E5-8B2535014930.dita"><linktext>Image Conversion
Overview</linktext></link>
<link href="GUID-6DC34798-86CE-537D-B3B8-9A94FF77B283.dita"><linktext>Image Encoding
Tutorial</linktext></link>
<link href="GUID-B10B048F-37FF-53E7-92B9-83F8C197566A.dita"><linktext>Image Decoding
Tutorial</linktext></link>
<link href="GUID-A825B62E-B5F6-5FDD-B267-E47103D57FD8.dita"><linktext>Guide to
Symbian supplied Codecs </linktext></link>
</related-links></concept>