Ticket #259: 259-v1.patch

File 259-v1.patch, 10.0 KB (added by danielk, 14 years ago)

Possible fix

  • libs/libmythtv/avformatdecoder.cpp

     
    167167      audio_sample_size(-1), audio_sampling_rate(-1), audio_channels(-1),
    168168      do_ac3_passthru(false), wantedAudioStream(-1),
    169169      audio_check_1st(2), audio_sampling_rate_2nd(0), audio_channels_2nd(0),
    170       wantedSubtitleStream(-1)
     170      // Subtitles
     171      languagePreference(iso639_get_language_key_list()),
     172      wantedSubtitleStream(),
     173      selectedSubtitleStream()
    171174{
    172175    bzero(&params, sizeof(AVFormatParameters));
    173176    bzero(prvpkt, 3 * sizeof(char));
     
    835838    audio_sampling_rate_2nd = -1;
    836839    audio_channels_2nd = -1;
    837840
     841    map<int,uint> lang_cnt;
     842
    838843    for (int i = 0; i < ic->nb_streams; i++)
    839844    {
    840845        AVCodecContext *enc = ic->streams[i]->codec;
     
    989994
    990995        if (enc->codec_type == CODEC_TYPE_SUBTITLE)
    991996        {
    992             subtitleStreams.push_back( i );
     997            int lang = -1, lang_indx = 0;
     998            if (ic->streams[i]->language)
     999            {
     1000                lang = iso639_str3_to_key(ic->streams[i]->language);
     1001                lang = iso639_key_to_canonical_key(lang);
     1002                lang_indx = lang_cnt[lang];
     1003                lang_cnt[lang]++;
     1004            }
     1005            subtitleStreams.push_back(SubtitleInfo(i, lang, lang_indx));
    9931006        }
    9941007
    9951008        if (enc->codec_type == CODEC_TYPE_AUDIO)
     
    18691882}
    18701883
    18711884
    1872 void AvFormatDecoder::incCurrentSubtitleTrack()
     1885void AvFormatDecoder::incCurrentSubtitleTrack(void)
    18731886{
    1874     if (subtitleStreams.size())
    1875     {
    1876         int tempTrackNo = currentSubtitleTrack;
    1877         ++tempTrackNo;
    1878         if (tempTrackNo > (int)(subtitleStreams.size() - 1))
    1879             tempTrackNo = 0;
    1880 
    1881         currentSubtitleTrack = tempTrackNo;
    1882         wantedSubtitleStream = subtitleStreams[currentSubtitleTrack];
    1883     }
     1887    int numStreams = (int)subtitleStreams.size();
     1888    int next       = (currentSubtitleTrack+1) % numStreams;
     1889    setCurrentSubtitleTrack((!numStreams) ? -1 : next);
    18841890}
    18851891
    1886 void AvFormatDecoder::decCurrentSubtitleTrack()
     1892void AvFormatDecoder::decCurrentSubtitleTrack(void)
    18871893{
    1888     if (subtitleStreams.size())
    1889     {
    1890         int tempTrackNo = currentSubtitleTrack;
    1891         --tempTrackNo;
    1892         if (tempTrackNo < 0)
    1893             tempTrackNo = subtitleStreams.size() - 1;
    1894 
    1895         currentSubtitleTrack = tempTrackNo;
    1896         wantedSubtitleStream = subtitleStreams[currentSubtitleTrack];
    1897     }
     1894    int numStreams = (int)subtitleStreams.size();
     1895    int next       = (currentSubtitleTrack < 0) ? 0 : currentSubtitleTrack;
     1896    next           = (next+numStreams-1) % numStreams;
     1897    setCurrentSubtitleTrack((!numStreams) ? -1 : next);
    18981898}
    18991899
    19001900bool AvFormatDecoder::setCurrentSubtitleTrack(int trackNo)
    19011901{
    1902     if (trackNo < 0)
    1903         trackNo = -1;
    1904     else if (trackNo >= (int)subtitleStreams.size())
     1902    if (trackNo >= (int)subtitleStreams.size())
    19051903        return false;
    19061904
    1907     currentSubtitleTrack = trackNo;
    1908     if (currentSubtitleTrack < 0)
    1909         return false;
    1910 
    1911     wantedSubtitleStream = subtitleStreams[currentSubtitleTrack];
    1912 
    1913     return true;
     1905    currentSubtitleTrack = max(-1, trackNo);
     1906    if (currentSubtitleTrack > 0)
     1907    {
     1908        wantedSubtitleStream   = subtitleStreams[currentSubtitleTrack];
     1909        selectedSubtitleStream = subtitleStreams[currentSubtitleTrack];
     1910        return true;
     1911    }
     1912    return false;
    19141913}
    19151914
    1916 QStringList AvFormatDecoder::listSubtitleTracks() const
     1915QStringList AvFormatDecoder::listSubtitleTracks(void) const
    19171916{
    19181917    QStringList list;
    1919     int num_tracks = subtitleStreams.size();
    1920     int track;
    1921    
    1922     for (track = 0; track < num_tracks; track++)
     1918
     1919    for (uint i = 0; i < subtitleStreams.size(); i++)
    19231920    {
    1924         AVStream *s = ic->streams[subtitleStreams[track]];
    1925        
    1926         if (!s)
    1927             continue;
    1928        
    1929         QString t = QString("%1: ").arg(track + 1);
    1930        
    1931         if (strlen(s->language) > 0)
    1932         {
    1933             t += iso639_str_toName((unsigned char *)(s->language));
    1934             t += " ";
    1935         }
    1936          
    1937         list += t;
     1921        QString msg  = iso639_key_toName(subtitleStreams[i].language);
     1922        msg          = msg.isEmpty() ? "?" : msg;
     1923        list        += QString("%1: %2 ").arg(i+1).arg(msg);
    19381924    }
    1939    
     1925
    19401926    return list;
    19411927}
    19421928
    1943 // in case there's only one subtitle language available, always choose it
    1944 //
    1945 // if more than one subtitle languages are found, the best one is
    1946 // picked according to the ISO639Language[0..] settings
    1947 //
    1948 // in case there are no ISOLanguage[0..] settings, or no preferred language
    1949 // is found, the first found subtitle stream is chosen
    1950 bool AvFormatDecoder::autoSelectSubtitleTrack()
     1929/** \fn AvFormatDecoder::autoSelectSubtitleTrack(void)
     1930 *  \brief Select best subtitle track.
     1931 *
     1932 *   If case there's only one subtitle available, always choose it.
     1933 *
     1934 *   If there is a user selected subtitle we try to find it.
     1935 *
     1936 *   If we can't find the user selected subtitle we try to
     1937 *   picked according to the ISO639Language[0..] settings.
     1938 *
     1939 *   In case there are no ISOLanguage[0..] settings, or no preferred language
     1940 *   is found, the first found subtitle stream is chosen
     1941 */
     1942bool AvFormatDecoder::autoSelectSubtitleTrack(void)
    19511943{
    1952     if (!subtitleStreams.size())
     1944    uint numStreams = subtitleStreams.size();
     1945
     1946    if ((currentSubtitleTrack > 0) && (currentSubtitleTrack < (int)numStreams))
     1947        return true; // subtitle already selected
     1948
     1949    if (!numStreams)
    19531950    {
    19541951        currentSubtitleTrack = -1;
    1955         wantedSubtitleStream = -1;
    1956         return false;
     1952        selectedSubtitleStream.av_stream_index = -1;
     1953        return false; // no subtitles available
    19571954    }
    19581955
    1959     int maxTracks = (subtitleStreams.size() - 1);
     1956    int selectedTrack = (1 == numStreams) ? 0 : -1;
    19601957
    1961     int selectedTrack = -1;
    1962    
    1963     // go through all preferred languages and pick the best found
    1964     QStringList langPref = iso639_get_language_list();
    1965     QStringList::iterator l = langPref.begin();
    1966     for (; l != langPref.end() && selectedTrack == -1; ++l)
     1958    if ((selectedTrack < 0) && wantedSubtitleStream.language)
    19671959    {
    1968         for (int track = 0; track < maxTracks; track++)
     1960        // Try to reselect user selected subtitle stream.
     1961        // This should find the stream after a commercial
     1962        // break and in some cases after a channel change.
     1963        int  wlang = wantedSubtitleStream.language;
     1964        uint windx = wantedSubtitleStream.language_index;
     1965        for (uint i = 0; i < numStreams; i++)
    19691966        {
    1970             int tempStream = subtitleStreams[track];
    1971             AVStream* st = ic->streams[tempStream];
     1967            if (wlang == subtitleStreams[i].language)
     1968                selectedTrack = i;
     1969            if (windx == subtitleStreams[i].language_index)
     1970                break;
     1971        }
     1972    }
    19721973
    1973             if (st->language == *l)
     1974    if (selectedTrack < 0)
     1975    {
     1976        // Find first subtitle stream that matches a language in
     1977        // order of most preferred to least preferred language.
     1978        vector<int>::iterator it = languagePreference.begin();
     1979        for (; (it != languagePreference.end()) && (selectedTrack < 0); ++it)
     1980        {
     1981            for (uint i = 0; i < numStreams; i++)
    19741982            {
    1975                 selectedTrack = track;
    1976                 break;
     1983                if (*it == subtitleStreams[i].language)
     1984                {
     1985                    selectedTrack = i;
     1986                    break;
     1987                }
    19771988            }
    19781989        }
    19791990    }
    1980    
    1981     if (selectedTrack == -1)
    1982     {
    1983         selectedTrack = 0;
    1984     }
    19851991
    1986     currentSubtitleTrack = selectedTrack;
    1987     wantedSubtitleStream = subtitleStreams[currentSubtitleTrack];
     1992    currentSubtitleTrack = (selectedTrack < 0) ? 0 : -1;
     1993    selectedSubtitleStream = subtitleStreams[currentSubtitleTrack];
     1994    if (!wantedSubtitleStream.language)
     1995        wantedSubtitleStream = selectedSubtitleStream;
    19881996     
    19891997    return true;
    19901998}
    19911999
    1992 
    1993 
    19942000bool AvFormatDecoder::GetFrame(int onlyvideo)
    19952001{
    19962002    AVPacket *pkt = NULL;
     
    20132019        autoSelectAudioTrack();
    20142020    }
    20152021
    2016     if ((currentSubtitleTrack == -1 ||
    2017         currentSubtitleTrack >= (int)subtitleStreams.size()) &&
    2018         subtitleStreams.size() > 0)
    2019     {
    2020         autoSelectSubtitleTrack();
    2021     }
     2022    autoSelectSubtitleTrack();
    20222023
    20232024    bool skipaudio = (lastvpts == 0);
    20242025
     
    23362337                    int gotSubtitles = 0;
    23372338                    AVSubtitle subtitle;
    23382339
    2339                     if (pkt->stream_index == wantedSubtitleStream)
     2340                    if (pkt->stream_index ==
     2341                        selectedSubtitleStream.av_stream_index)
    23402342                    {
    23412343                        avcodec_decode_subtitle(context, &subtitle,
    23422344                                                &gotSubtitles, ptr, len);
  • libs/libmythtv/avformatdecoder.h

     
    2020
    2121extern "C" void HandleStreamChange(void*);
    2222
     23class SubtitleInfo
     24{
     25  public:
     26    SubtitleInfo() : av_stream_index(-1), language(0), language_index(0) {}
     27    SubtitleInfo(int a, int b, uint c)
     28        : av_stream_index(a), language(b), language_index(c) {}
     29  public:
     30    int  av_stream_index;
     31    int  language; ///< ISO639 cannonical language key
     32    uint language_index;
     33};
     34typedef vector<SubtitleInfo> sub_vec_t;
     35
    2336/// A decoder for video files.
    2437
    2538/// The AvFormatDecoder is used to decode non-NuppleVideo files.
     
    197210    int               audio_sampling_rate_2nd; ///< Used by CheckAudioParams
    198211    int               audio_channels_2nd;      ///< Used by CheckAudioParams
    199212
    200     QValueVector<int> subtitleStreams;
    201     int wantedSubtitleStream;
     213    sub_vec_t         subtitleStreams;
     214    vector<int>       languagePreference;
     215    SubtitleInfo      wantedSubtitleStream;
     216    SubtitleInfo      selectedSubtitleStream;
    202217};
    203218
    204219#endif