mmplugins/mmfwplugins/src/Plugin/Controller/Video/AviPlayController/srtdecoder/srtdecoder.cpp
author hgs
Wed, 13 Oct 2010 12:45:32 +0100
changeset 2 5c1df44f2eed
parent 0 b8ed18f6c07b
permissions -rw-r--r--
2010wk42_01
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
     1
// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
     2
// All rights reserved.
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
     3
// This component and the accompanying materials are made available
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
     4
// under the terms of "Eclipse Public License v1.0"
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
     5
// which accompanies this distribution, and is available
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
     7
//
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
     8
// Initial Contributors:
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
     9
// Nokia Corporation - initial contribution.
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    10
//
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    11
// Contributors:
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    12
//
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    13
// Description:
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    14
//
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    15
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    16
#include <bitdev.h> 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    17
#include <fbs.h> 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    18
#include <gdi.h> 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    19
#include <utf.h> 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    20
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    21
#include "subtitlesource.h"
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    22
#include "srtdecoder.h"
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    23
#include "srtframe.h"
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    24
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    25
// Define the separators for each subtitle frame in SRT file
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    26
_LIT8(KSrtFrameSeparator1, "\r\n\r\n" );
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    27
_LIT8(KSrtFrameSeparator2, "\n\n" );
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    28
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    29
// The length of the separators
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    30
const TInt KSrtFrameSeparator1Len = 4;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    31
const TInt KSrtFrameSeparator2Len = 2;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    32
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    33
// The margin size
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    34
const TInt KSrtBmpMarginWidth = 6;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    35
const TInt KSrtBmpMarginHeight = 6;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    36
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    37
// The width of subtitle region is the same as the width of the video region, while the height is 33 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    38
// percent of the height of the video region. 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    39
const TInt KSrtSubtitleRegionYFactor = 33;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    40
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    41
// Define panic category
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    42
_LIT(KSrtSubtitleDecoderPanicCategory, "SrtSubDec");
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    43
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    44
// TSrtSubtitleDecoderPanics is an enumeration with the following entries:
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    45
// EBadCall indicates a bad call
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    46
enum TSrtSubtitleDecoderPanics
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    47
    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    48
    ESrtBadCall = 1,
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    49
    ESrtUnexpected,
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    50
    ESrtNotStarted,
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    51
    ESrtAlreadyStarted
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    52
    };
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    53
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    54
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    55
/** Constructor with a reference to the subtitle source 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    56
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    57
@param aSubtitleSource a reference to the subtitle source
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    58
*/ 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    59
CSrtSubtitleDecoder::CSrtSubtitleDecoder(MSubtitleSource& aSubtitleSource) : 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    60
    iSource(aSubtitleSource)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    61
    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    62
    }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    63
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    64
EXPORT_C CSrtSubtitleDecoder::~CSrtSubtitleDecoder()
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    65
    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    66
    delete iFrameParser;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    67
    iDecodeBuffer.Close();
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    68
    }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    69
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    70
/** Allocates and constructs a srt subtitle decoder 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    71
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    72
@param aSubtitleSource a reference to the subtitle source
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    73
@return A pointer to the new object. 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    74
@leave If an error occurs, the method will leave with a system-wide error code. 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    75
*/    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    76
EXPORT_C CSrtSubtitleDecoder* CSrtSubtitleDecoder::NewL(MSubtitleSource& aSubtitleSource)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    77
    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    78
    CSrtSubtitleDecoder* self = new(ELeave) CSrtSubtitleDecoder(aSubtitleSource);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    79
    CleanupStack::PushL(self);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    80
    self->ConstructL();
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    81
    CleanupStack::Pop(self);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    82
    return self;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    83
    }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    84
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    85
/** Initialises the decoder
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    86
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    87
@leave If an error occurs, the method will leave with a system-wide error code.
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    88
*/
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    89
void CSrtSubtitleDecoder::ConstructL()
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    90
    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    91
    iFrameParser = CSrtFrame::NewL();
2
5c1df44f2eed 2010wk42_01
hgs
parents: 0
diff changeset
    92
    iDecodeBuffer.CreateL(KSubtitleDecoderBufferLength);
0
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    93
    }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    94
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    95
EXPORT_C TInt CSrtSubtitleDecoder::CalculateSubtitleRegion(const TRect& aScreenSize, TRect& aSubtitleRegion)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    96
    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    97
    // TRect::IsEmpty is not used because the following test tests the minus values.
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    98
    if ((aScreenSize.iBr.iX < 0) || (aScreenSize.iBr.iY < 0) || 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
    99
        (aScreenSize.iTl.iX < 0) || (aScreenSize.iTl.iY < 0))
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   100
        {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   101
        return KErrArgument;  
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   102
        }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   103
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   104
    if ((aScreenSize.iBr.iX <= aScreenSize.iTl.iX) || (aScreenSize.iBr.iY <= aScreenSize.iTl.iY))
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   105
        {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   106
        return KErrArgument; 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   107
        }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   108
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   109
    TPoint topleft;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   110
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   111
    topleft.iX = aScreenSize.iTl.iX;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   112
    topleft.iY = aScreenSize.iTl.iY + aScreenSize.Height() * (100 - KSrtSubtitleRegionYFactor) / 100; 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   113
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   114
    aSubtitleRegion.SetRect(topleft, aScreenSize.iBr);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   115
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   116
    return KErrNone;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   117
    }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   118
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   119
/** Calculate the number of the characters in the first line. The full words are supposed to be displayed 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   120
unless the length of a word is bigger than one line space. 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   121
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   122
@param aFont The font in current use.
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   123
@param aText The descriptor
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   124
@param aWidthInPixels The available width for character display.
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   125
@param aNumOfCharsToSkip The number of characters to skip, it can be 0, 1 (\n) or 2 (\r\n) 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   126
@return The number of characters which will be able to be displayed without exceeding the specified width. 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   127
The count starts from the beginning of the descriptor. 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   128
*/   
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   129
TInt CSrtSubtitleDecoder::CalculateCharsInNextLine(const CFont &aFont, const TDesC &aText, TInt aWidthInPixels, TInt& aNumOfCharsToSkip)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   130
    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   131
    const TChar KMMFSubtitleCharSpace(' ');
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   132
    const TChar KMMFSubtitleCharCR('\r');
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   133
    const TChar KMMFSubtitleCharLF('\n');
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   134
    TInt charsInLine = aFont.TextCount(aText, aWidthInPixels);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   135
    aNumOfCharsToSkip = 0;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   136
        
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   137
    if (charsInLine < aText.Length())
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   138
        {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   139
        // For finding the last space of a descriptor which is not very big, using a simple loop 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   140
        // shall be more efficient than using TLex
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   141
        for (TInt i = charsInLine; i > 0; i--)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   142
            {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   143
            if (KMMFSubtitleCharSpace == aText[i - 1])
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   144
                {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   145
                charsInLine = i;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   146
                break;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   147
                }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   148
            }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   149
        }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   150
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   151
    // Check \r\n or \n, the following loop is more efficient than TDesC::Find() in most cases 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   152
    // because both \r\n and \n are handled in one loop. 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   153
    for (TInt j = 0; j < charsInLine; j++)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   154
        {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   155
        if (KMMFSubtitleCharLF == aText[j])
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   156
            {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   157
            if (j > 0)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   158
                {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   159
                // ignore \r if there is a \n
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   160
                if (KMMFSubtitleCharCR == aText[j - 1])
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   161
                    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   162
                    charsInLine = j;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   163
                    aNumOfCharsToSkip = 2;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   164
                    }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   165
                else
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   166
                    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   167
                    charsInLine = j + 1;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   168
                    aNumOfCharsToSkip = 1;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   169
                    }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   170
                }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   171
            else
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   172
                {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   173
                charsInLine = j + 1;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   174
                aNumOfCharsToSkip = 1;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   175
                }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   176
            break;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   177
            }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   178
        }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   179
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   180
    return charsInLine;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   181
    }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   182
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   183
/** Based on a descriptor containing a SRT subtitle frame, the function generates a single frame of 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   184
subtitle animation for the current time and outputs the region of the subtitle frame that has been 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   185
updated.
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   186
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   187
@param aContent The subtitle frame as a descriptor
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   188
@param aSubtitleFrame Reference to the current subtitle frame
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   189
@param aDirtyRegion The decoder outputs the region of the subtitle frame that has been updated. 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   190
    i.e. the region that now contains new subtitle content.
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   191
@leave If an error occurs, the method will leave with a system-wide error code. 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   192
*/
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   193
void CSrtSubtitleDecoder::DecodeSubtitleContentL(const TDesC8& aContent, CFbsBitmap& aSubtitleFrame, TRect& aDirtyRegion)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   194
    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   195
    TSize bmpSize = aSubtitleFrame.SizeInPixels(); 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   196
    TSize modifiedBmpSize;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   197
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   198
    // the following value of "2" means two side of margin. 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   199
    modifiedBmpSize.iHeight = bmpSize.iHeight - KSrtBmpMarginHeight * 2;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   200
    modifiedBmpSize.iWidth = bmpSize.iWidth - KSrtBmpMarginWidth * 2;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   201
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   202
    // test if the size of the bitmap is valid after taking margin into account   
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   203
    if ((modifiedBmpSize.iHeight > 0) && (modifiedBmpSize.iWidth > 0))
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   204
        {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   205
        // prepare and populate the bitmap
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   206
        CFbsBitmapDevice* bmpDevice = CFbsBitmapDevice::NewL(&aSubtitleFrame);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   207
        CleanupStack::PushL(bmpDevice);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   208
        
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   209
        CFbsBitGc* bitmapContext = CFbsBitGc::NewL(); //Create a GC to draw to the bitmap
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   210
        bitmapContext->Activate(bmpDevice);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   211
        
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   212
        CleanupStack::PushL(bitmapContext);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   213
        
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   214
        bitmapContext->SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   215
        
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   216
        // Use a white color (R=255, G=255, B=255) with alpha value of 0. 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   217
        TRgb transparentWhite(255, 255, 255, 0);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   218
        bitmapContext->SetBrushColor(transparentWhite);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   219
        
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   220
        bitmapContext->Clear(); 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   221
        
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   222
        bitmapContext->SetDrawMode(CGraphicsContext::EDrawModePEN);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   223
        
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   224
        bitmapContext->SetPenStyle(CGraphicsContext::ESolidPen);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   225
        bitmapContext->SetPenColor(KRgbBlack);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   226
        
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   227
        HBufC* content = CnvUtfConverter::ConvertToUnicodeFromUtf8L(aContent);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   228
        CleanupStack::PushL(content);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   229
        
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   230
        // try to set up font
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   231
        CFont *font = NULL;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   232
        TFontSpec fontSpec(KSrtTargetTypefaceName, KSrtTargetTypefaceHeightInTwips);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   233
        User::LeaveIfError(bmpDevice->GetNearestFontToDesignHeightInTwips(font, fontSpec));
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   234
            
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   235
        bitmapContext->UseFont(font);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   236
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   237
        TInt maxCharWidthInPixels = font->MaxCharWidthInPixels();
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   238
        TInt heightInPixels = font->HeightInPixels();
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   239
        TInt maxLines = modifiedBmpSize.iHeight / heightInPixels;    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   240
        TInt maxCharsPerLine = modifiedBmpSize.iWidth / maxCharWidthInPixels; 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   241
        TInt charsInLine = 0;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   242
        TInt currentRow = 0;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   243
        TPoint drawPosition;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   244
        drawPosition.iX = KSrtBmpMarginWidth;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   245
        drawPosition.iY = KSrtBmpMarginHeight + heightInPixels;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   246
        TInt unvisitedChars = content->Length();
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   247
        TInt lineStartPos = 0;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   248
        TInt numOfCharsToSkip = 0;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   249
        
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   250
        if ((maxLines > 0) && (maxCharsPerLine > 0))
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   251
            {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   252
            do
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   253
                {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   254
                TPtrC ptrUnvisitedDesc = content->Right(unvisitedChars);                
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   255
                
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   256
                charsInLine = CalculateCharsInNextLine(*font, ptrUnvisitedDesc, modifiedBmpSize.iWidth, numOfCharsToSkip); 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   257
                if (charsInLine > 0)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   258
                    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   259
                    if (charsInLine > numOfCharsToSkip)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   260
                        {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   261
                        TPtrC ptrLine = content->Mid(lineStartPos, charsInLine - numOfCharsToSkip);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   262
                        // try to draw text line by line
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   263
                        // Note that aPosition in DrawText indicates the bottom left of the first character. 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   264
                        bitmapContext->DrawText(ptrLine, drawPosition);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   265
                    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   266
                        drawPosition.iY += heightInPixels; 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   267
                        currentRow++;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   268
                        }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   269
                        
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   270
                    lineStartPos += charsInLine;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   271
                    unvisitedChars -= charsInLine;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   272
                    }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   273
                }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   274
            while(charsInLine > 0 && currentRow < maxLines);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   275
            
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   276
            // update the dirty region
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   277
            aDirtyRegion.iTl.SetXY(KSrtBmpMarginWidth, KSrtBmpMarginHeight);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   278
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   279
            TInt actualMaxCharsPerLine = 0;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   280
            actualMaxCharsPerLine = Min(content->Length(), maxCharsPerLine);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   281
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   282
            aDirtyRegion.iBr.SetXY(
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   283
                KSrtBmpMarginWidth + actualMaxCharsPerLine * maxCharWidthInPixels,
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   284
                KSrtBmpMarginHeight + currentRow * heightInPixels + font->FontMaxDescent());
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   285
            }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   286
        else
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   287
            {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   288
            // bitmap too small for the font
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   289
            User::Leave(KErrArgument);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   290
            }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   291
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   292
        bmpDevice->ReleaseFont(font);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   293
        bitmapContext->DiscardFont();
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   294
        
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   295
        CleanupStack::PopAndDestroy(3, bmpDevice); // content, bitmapContext, bmpDevice
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   296
        }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   297
    else
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   298
        {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   299
        // bitmap too small or the length of content is 0
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   300
        User::Leave(KErrArgument);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   301
        }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   302
    }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   303
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   304
/** Try to get the next valid frame 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   305
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   306
@param aSearchByVideoPosition Indicate if search for the next valid frame matching aVideoPosition
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   307
@param aVideoPosition The video position in microsecond
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   308
@leave If an error occurs, the method will leave with a system-wide error code. 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   309
*/
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   310
void CSrtSubtitleDecoder::GetNextValidFrameL(TBool aSearchByVideoPosition, TInt64 aVideoPosition)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   311
    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   312
    TInt decoderBufferMaxLen = iDecodeBuffer.MaxLength();
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   313
    TInt errorFrame = KErrNone;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   314
    TInt error = KErrNone;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   315
    TInt sepLen = 0;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   316
    TInt i = 0;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   317
    TChar currentChar = 0;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   318
    TBool frameFound = EFalse;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   319
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   320
    if (iLastFrame)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   321
    	{
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   322
    	User::Leave(KErrEof);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   323
    	}
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   324
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   325
    while (!frameFound)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   326
        {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   327
        // if a frame is not available in iDecodeBuffer, fill iBuffer until CRLFCRLF is available in iBuffer
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   328
        TPtrC8 restOfData = iDecodeBuffer.Right(iDecodeBuffer.Length() - iDecodeBufferPosition);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   329
        TInt sepPosition = 0;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   330
        
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   331
        // try to extract a frame from iDecodeBuffer
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   332
        errorFrame = GetFrameSeparatorInfo(restOfData, sepLen, sepPosition);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   333
        if (KErrNotFound != errorFrame)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   334
            {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   335
            User::LeaveIfError(errorFrame);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   336
            }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   337
            
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   338
        // if no frame can be extracted, read source until a frame is available or get an EOF error.
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   339
        while (KErrNotFound == errorFrame)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   340
            {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   341
            // move the unvisited data in decode buffer to the head before read from the source
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   342
            if (iDecodeBufferPosition != 0)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   343
                {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   344
                // move the unvisited data in decode buffer to the head
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   345
                if (iDecodeBufferPosition <= iDecodeBuffer.Length() - 1)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   346
                    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   347
                    TPtrC8 newSubtitleFrame = iDecodeBuffer.Right(iDecodeBuffer.Length() - (iDecodeBufferPosition));
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   348
                    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   349
                    // use iBuffer to hold the preserved data when rotating data in iDecodeBuffer
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   350
                    if (iBuffer.MaxLength() < newSubtitleFrame.Length())
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   351
                        {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   352
                        // Some data in iBuffer make iDecodeBuffer hold at least one frame, and so
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   353
                        // iBuffer should always be larger than the preserved data in iDecodeBuffer
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   354
                        User::Panic(KSrtSubtitleDecoderPanicCategory, ESrtUnexpected);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   355
                        }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   356
                        
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   357
                    iBuffer.Copy(newSubtitleFrame);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   358
                    iDecodeBuffer.Copy(iBuffer);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   359
                    }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   360
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   361
                iDecodeBufferPosition = 0;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   362
                }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   363
                
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   364
            error = iSource.GetBuffer(iBuffer);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   365
            if ((KErrNone != error) && (KErrEof != error))
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   366
                {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   367
                User::Leave(error);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   368
                }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   369
            
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   370
            if (iBuffer.Length() > 0)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   371
                {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   372
                TInt bufLen = iDecodeBuffer.Length();
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   373
                TInt newBufLen = iBuffer.Length();
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   374
                
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   375
                if (decoderBufferMaxLen < newBufLen + bufLen)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   376
                    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   377
                    iDecodeBuffer.ReAllocL(newBufLen + bufLen);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   378
                    decoderBufferMaxLen = iDecodeBuffer.MaxLength();
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   379
                    }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   380
                iDecodeBuffer.Append(iBuffer);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   381
                }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   382
                
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   383
            if (KErrEof == error)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   384
                {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   385
                // reach the end of the subtitle source but cannot find new line separators.  Frame 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   386
                // ends at EOF marker then.  No more frames can be read after this one.
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   387
                sepLen = 0;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   388
                sepPosition = iDecodeBuffer.Length();
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   389
                errorFrame = KErrNone;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   390
                if (iLastFrame)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   391
                	{
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   392
                	User::Leave(KErrEof);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   393
                	}
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   394
                iLastFrame = ETrue;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   395
                }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   396
            else
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   397
            	{
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   398
            	errorFrame = GetFrameSeparatorInfo(iDecodeBuffer, sepLen, sepPosition);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   399
            	}
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   400
            
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   401
            if (KErrNotFound != errorFrame)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   402
                {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   403
                User::LeaveIfError(errorFrame);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   404
                }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   405
            }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   406
        
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   407
        // extract a possible frame
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   408
        TPtrC8 subtitleFrameDescriptor = iDecodeBuffer.Mid(iDecodeBufferPosition, sepPosition);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   409
        
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   410
        // Find the start of the next frame, and update the current position of the decode buffer by 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   411
        // the following method: from the start of iDecodeBuffer, find the position of the first digit 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   412
        // character after the first frame separator. 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   413
        // Not the current position of the decode buffer is updated before parsing the frame, so the 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   414
        // potential invalid frame will be skipped.  
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   415
        iDecodeBufferPosition += sepPosition + sepLen;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   416
        TInt firstDigitPosFromCurrentPos = KErrNotFound;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   417
        for (i = iDecodeBufferPosition; i < iDecodeBuffer.Length(); i++)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   418
            {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   419
            currentChar = iDecodeBuffer[i];
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   420
            if (currentChar.IsDigit())
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   421
                {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   422
                firstDigitPosFromCurrentPos = i;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   423
                break;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   424
                }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   425
            }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   426
        if (KErrNotFound == firstDigitPosFromCurrentPos) 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   427
            {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   428
            iDecodeBufferPosition = iDecodeBuffer.Length() - 1;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   429
            }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   430
        else
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   431
            {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   432
            iDecodeBufferPosition = firstDigitPosFromCurrentPos;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   433
            }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   434
        
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   435
        // parse the frame 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   436
        TRAPD(parseError, iFrameParser->ParseL(subtitleFrameDescriptor, aSearchByVideoPosition, aVideoPosition));
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   437
        if (KErrNone == parseError)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   438
            {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   439
            frameFound = ETrue;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   440
            if (!aSearchByVideoPosition)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   441
                {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   442
                // skip the past frames, such as 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   443
                // 2\r\n00:00:02,000 --> 00:00:04,000\r\nhome\r\n\r\n
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   444
                // 1\r\n00:00:00,000 --> 00:00:02,000\r\nwelcome\r\n\r\n
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   445
                // 3\r\n00:00:04,000 --> 00:00:06,000\r\nagain
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   446
                if (iFrameParser->EndTime() < iEndTimeOfLastValidFrame)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   447
                    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   448
                    frameFound = EFalse;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   449
                    }  
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   450
                else
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   451
                    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   452
                    iEndTimeOfLastValidFrame = iFrameParser->EndTime();
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   453
                    }  
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   454
                }      
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   455
            else
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   456
                {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   457
                iEndTimeOfLastValidFrame = iFrameParser->EndTime();
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   458
                }    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   459
            }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   460
        else
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   461
            {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   462
            if (KErrArgument != parseError)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   463
                {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   464
                User::Leave(parseError);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   465
                }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   466
            }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   467
        }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   468
    }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   469
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   470
/** The decoder generates a single frame of subtitle animation for the current time.   
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   471
The decoder maintains track of the video position. The video position can be updated 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   472
via a call to MSubtitleDecoder::SetVideoPosition(). 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   473
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   474
@param aSubtitleFrame Reference to the current subtitle frame
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   475
@param aDirtyRegion The decoder outputs the region of the subtitle frame that has been updated. 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   476
    i.e. the region that now contains new subtitle content.
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   477
@param aDisplayTime The time in microseconds from the current stream position that the subtitle is due. 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   478
    DevSubtitle will draw aSubtitleFrame after aDisplayTime has elapsed.
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   479
@param aDisplayDuration The time in microseconds that this frame should be displayed for. The CRP will clear 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   480
    this frame after aDisplayFor microseconds
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   481
@leave If an error occurs, the method will leave with a system-wide error code.
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   482
*/   
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   483
EXPORT_C void CSrtSubtitleDecoder::GetNextFrameL(CFbsBitmap& aSubtitleFrame, TRect& aDirtyRegion, TTimeIntervalMicroSeconds& aDisplayTime, TTimeIntervalMicroSeconds& aDisplayDuration)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   484
    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   485
    if (!iStarted)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   486
        {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   487
        User::Panic(KSrtSubtitleDecoderPanicCategory, ESrtNotStarted);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   488
        }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   489
        
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   490
    TTime currentTime;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   491
    currentTime.UniversalTime();
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   492
    TTimeIntervalMicroSeconds elapsedTime = currentTime.MicroSecondsFrom(iStartSystemTime);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   493
    TInt64 currentVideoPositionValue = elapsedTime.Int64() + iStartVideoPosition;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   494
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   495
    if (iFirstSearch)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   496
        {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   497
        // skip the past frame
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   498
        GetNextValidFrameL(ETrue, currentVideoPositionValue);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   499
            
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   500
        iFirstSearch = EFalse;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   501
        }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   502
    else
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   503
        {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   504
        // get the next frame
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   505
        GetNextValidFrameL(EFalse, 0);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   506
        }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   507
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   508
    TInt64 elapsedDuration = 0;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   509
    // if start time <= current video time, this frame needs to be started immediately.    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   510
    if (iFrameParser->StartTime() <= currentVideoPositionValue)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   511
        {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   512
        aDisplayTime = 0;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   513
        elapsedDuration = currentVideoPositionValue - iFrameParser->StartTime();
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   514
        }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   515
    else
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   516
        {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   517
        aDisplayTime = iFrameParser->StartTime() - currentVideoPositionValue;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   518
        }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   519
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   520
    // if end time < current video time, this duration becomes 0.
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   521
    if (iFrameParser->EndTime() <= currentVideoPositionValue)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   522
        {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   523
        aDisplayDuration = 0;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   524
        }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   525
    else
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   526
        {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   527
        aDisplayDuration = iFrameParser->Duration() - elapsedDuration;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   528
        }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   529
            
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   530
    // decode the content into bitmap and get dirty region
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   531
    TPtrC8 ptrContent = iFrameParser->Content();
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   532
    DecodeSubtitleContentL(ptrContent, aSubtitleFrame, aDirtyRegion);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   533
    }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   534
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   535
EXPORT_C TLanguage CSrtSubtitleDecoder::SubtitleLanguageL()
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   536
    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   537
    return iSource.SubtitleLanguageL();
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   538
    }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   539
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   540
EXPORT_C void CSrtSubtitleDecoder::GetSupportedSubtitleLanguagesL(RArray<TLanguage>& aLanguages)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   541
    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   542
    iSource.GetSupportedSubtitleLanguagesL(aLanguages);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   543
    }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   544
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   545
EXPORT_C void CSrtSubtitleDecoder::SetSubtitleLanguageL(TLanguage aLanguage)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   546
    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   547
    iSource.SetSubtitleLanguageL(aLanguage);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   548
    }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   549
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   550
EXPORT_C void CSrtSubtitleDecoder::SetVideoPosition(const TTimeIntervalMicroSeconds& aPosition)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   551
    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   552
    if (aPosition < 0)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   553
        {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   554
        User::Panic(KSrtSubtitleDecoderPanicCategory, ESrtBadCall);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   555
        }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   556
        
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   557
    iStartVideoPosition = aPosition.Int64();
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   558
    iLastFrame = EFalse;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   559
    }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   560
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   561
EXPORT_C void CSrtSubtitleDecoder::Start()
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   562
    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   563
    if (iStarted)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   564
        {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   565
        User::Panic(KSrtSubtitleDecoderPanicCategory, ESrtAlreadyStarted);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   566
        }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   567
    iSource.SetPosition(0);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   568
    iStartSystemTime.UniversalTime();
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   569
    iStarted = ETrue;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   570
    iDecodeBufferPosition = 0;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   571
    iFirstSearch = ETrue;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   572
    iEndTimeOfLastValidFrame = 0;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   573
    iLastFrame = EFalse;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   574
    }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   575
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   576
EXPORT_C void CSrtSubtitleDecoder::Stop()
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   577
    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   578
    iSource.SetPosition(0);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   579
    iDecodeBuffer.SetLength(0);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   580
    iBuffer.SetLength(0);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   581
    iStartVideoPosition = 0; 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   582
    iStartSystemTime = 0;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   583
    iStarted = EFalse;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   584
    iDecodeBufferPosition = 0;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   585
    iLastFrame = EFalse;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   586
    }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   587
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   588
/** Searches for the first occurrence of the SRT frame separator (\r\n\r\n or \n\n) within this 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   589
    descriptor and return the length and the position of the separator.
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   590
        
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   591
@param aDes The buffer being searched
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   592
@param aSeparatorLength Output the length of the SRT frame separator
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   593
@param aPosition The offset of the SRT frame separator from the beginning of this descriptor's data.
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   594
@return A system-wide error code, KErrNotFound if the SRT frame separator cannot be found. 
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   595
*/
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   596
TInt CSrtSubtitleDecoder::GetFrameSeparatorInfo(const TDesC8& aDes, TInt& aSeparatorLength, TInt& aPosition)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   597
    {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   598
    TInt errCode = KErrNone;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   599
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   600
    aPosition = aDes.Find(KSrtFrameSeparator1);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   601
    if (KErrNotFound == aPosition)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   602
        {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   603
        aPosition = aDes.Find(KSrtFrameSeparator2);
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   604
        if (KErrNotFound == aPosition)
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   605
            {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   606
            errCode = KErrNotFound;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   607
            }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   608
        else
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   609
            {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   610
            aSeparatorLength = KSrtFrameSeparator2Len;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   611
            }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   612
        }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   613
    else
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   614
        {
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   615
        aSeparatorLength = KSrtFrameSeparator1Len;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   616
        }   
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   617
    
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   618
    return errCode;
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   619
    }
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   620
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   621
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   622
b8ed18f6c07b 2010wk40
hgs
parents:
diff changeset
   623