Ticket #2439: 2439-v1.patch

File 2439-v1.patch, 10.0 KB (added by danielk, 13 years ago)

Update patch (presentation portion)

  • libs/libmythtv/avformatdecoder.h

     
    185185    void SeekReset(long long, uint skipFrames, bool doFlush, bool discardFrames);
    186186
    187187    bool SetupAudioStream(void);
     188    bool SetupAudioStreamSubIndexes(bool wasDual, bool isDual);
    188189
    189190    /// Update our position map, keyframe distance, and the like.
    190191    /// Called for key frame packets.
  • libs/libmythtv/avformatdecoder.cpp

     
    14881488                lang_indx = lang_aud_cnt[lang];
    14891489                lang_aud_cnt[lang]++;
    14901490            }
    1491             tracks[kTrackTypeAudio].push_back(
    1492                 StreamInfo(i, lang, lang_indx, ic->streams[i]->id));
    14931491
     1492            if (ic->streams[i]->codec->avcodec_dual_language)
     1493            {
     1494                tracks[kTrackTypeAudio].push_back(
     1495                    StreamInfo(i, lang, lang_indx, ic->streams[i]->id, 0));
     1496                tracks[kTrackTypeAudio].push_back(
     1497                    StreamInfo(i, lang, lang_indx, ic->streams[i]->id, 1));
     1498            }
     1499            else
     1500            {
     1501                tracks[kTrackTypeAudio].push_back(
     1502                    StreamInfo(i, lang, lang_indx, ic->streams[i]->id));
     1503            }
     1504
    14941505            VERBOSE(VB_AUDIO, LOC + QString(
    14951506                        "Audio Track #%1 is A/V stream #%2 "
    14961507                        "and has %3 channels in the %4 language(%5).")
     
    15551566    return scanerror;
    15561567}
    15571568
     1569/** \fn AvFormatDecoder::SetupAudioStreamSubIndexes(bool, bool)
     1570 *  \brief Reacts to DUAL/STEREO changes on the fly and fix streams.
     1571 *
     1572 *  This function kicks in when a switch between dual and stereo
     1573 *  mpeg audio is detected. Such changes can and will happen at
     1574 *  any time.
     1575 *
     1576 *  It can only be used in the case where the mpeg file contains
     1577 *  exactly one audio stream that switches automatically between
     1578 *  stereo (1 language) and dual (2 unspecified languages) audio.
     1579 *
     1580 *  If this method returns true, the stream list has changed and
     1581 *  a new audio stream needs to be selected, usually using
     1582 *  AvFormatDecoder::autoSelectSubtitleTrack()
     1583 *
     1584 *  \param wasDual true if the stream used to contain dual audio
     1585 *  \param isDual true if the stream currently contains dual audio
     1586 *  \return true if a change was made
     1587 */
     1588bool AvFormatDecoder::SetupAudioStreamSubIndexes(bool wasDual, bool isDual)
     1589{
     1590    if (wasDual == isDual)
     1591    {
     1592        // No changes
     1593        return false;
     1594    }
     1595
     1596    QMutexLocker locker(&avcodeclock);
     1597    int numStreams = tracks[kTrackTypeAudio].size();
     1598    if (isDual)
     1599    {
     1600        if (numStreams != 1)
     1601            return false;
     1602
     1603        // Split stream in two (Language I + Language II)
     1604        tracks[kTrackTypeAudio].push_back(tracks[kTrackTypeAudio][0]);
     1605        tracks[kTrackTypeAudio][0].av_substream_index = 0;
     1606        tracks[kTrackTypeAudio][1].av_substream_index = 1;
     1607    }
     1608    else
     1609    {
     1610        if (numStreams != 2)
     1611            return false;
     1612
     1613        // Remove extra stream
     1614        tracks[kTrackTypeAudio][0].av_substream_index = -1;
     1615        tracks[kTrackTypeAudio].pop_back();
     1616    }
     1617
     1618    // Changed
     1619    return true;
     1620}
     1621
    15581622int get_avf_buffer(struct AVCodecContext *c, AVFrame *pic)
    15591623{
    15601624    AvFormatDecoder *nd = (AvFormatDecoder *)(c->opaque);
     
    23682432 *   preference:
    23692433 *
    23702434 *   1) The stream last selected by the user, which is
    2371  *      recalled as the Nth stream in the preferred language.
     2435 *      recalled as the Nth stream in the preferred language
     2436 *      or the Nth substream when audio is in dual language
     2437 *      format (each channel contains a different language track)
    23722438 *      If it can not be located we attempt to find a stream
    23732439 *      in the same language.
    23742440 *
     
    24352501    int selTrack = (1 == numStreams) ? 0 : -1;
    24362502    int wlang    = wtrack.language;
    24372503
     2504
     2505    if (selTrack < 0 && wtrack.av_substream_index >= 0)
     2506    {
     2507        VERBOSE(VB_AUDIO, LOC + "Trying to reselect audio sub-stream");
     2508        // Dual stream without language information: choose
     2509        // the previous (sub)stream that was kept in wtrack.
     2510        int substream_index = wtrack.av_substream_index;
     2511
     2512        for (uint i = 0; i < numStreams; i++)
     2513        {
     2514            if (atracks[i].av_substream_index == substream_index)
     2515            {
     2516                selTrack = i;
     2517                break;
     2518            }
     2519        }
     2520    }
     2521
    24382522    if ((selTrack < 0) && wlang >= -1 && numStreams)
    24392523    {
    24402524        VERBOSE(VB_AUDIO, LOC + "Trying to reselect audio track");
     
    25152599    return selTrack;
    25162600}
    25172601
     2602static void filter_audio_data(int channel, AudioInfo *audioInfo,
     2603                              char *buffer, int bufsize)
     2604{
     2605    // Only stereo -> mono (left or right) is supported
     2606    if (audioInfo->channels != 2)
     2607        return;
     2608
     2609    if (channel != 0 && channel != 1)
     2610        return;
     2611
     2612    const int samplesize = audioInfo->sample_size;
     2613    const int samples = bufsize / samplesize;
     2614    const int halfsample = samplesize/2;
     2615
     2616    const char *from;
     2617    char *to;
     2618
     2619    if (channel==0)
     2620    {
     2621        from = buffer;
     2622        to = buffer + halfsample;
     2623    }
     2624    else
     2625    {
     2626        from = buffer + halfsample;
     2627        to = buffer;
     2628    }
     2629
     2630    for (int sample = 0; sample < samples;
     2631         (sample++), (from += samplesize), (to += samplesize))
     2632    {
     2633        for(int bit = 0; bit < halfsample; bit++)
     2634            to[bit] = from[bit];
     2635    }
     2636}
     2637
    25182638bool AvFormatDecoder::GetFrame(int onlyvideo)
    25192639{
    25202640    AVPacket *pkt = NULL;
     
    27832903        avcodeclock.lock();
    27842904        int ctype  = curstream->codec->codec_type;
    27852905        int audIdx = selectedTrack[kTrackTypeAudio].av_stream_index;
     2906        int audSubIdx = selectedTrack[kTrackTypeAudio].av_substream_index;
    27862907        int subIdx = selectedTrack[kTrackTypeSubtitle].av_stream_index;
    27872908        avcodeclock.unlock();
    27882909
     
    27922913            {
    27932914                case CODEC_TYPE_AUDIO:
    27942915                {
     2916                    // detect switches between stereo and dual languages
     2917                    bool reselectAudioTrack =
     2918                        SetupAudioStreamSubIndexes(
     2919                            audSubIdx != -1,
     2920                            curstream->codec->avcodec_dual_language);
     2921
    27952922                    // detect channels on streams that need
    27962923                    // to be decoded before we can know this
    27972924                    if (!curstream->codec->channels)
     
    28012928                        ret = avcodec_decode_audio(
    28022929                            curstream->codec, audioSamples,
    28032930                            &data_size, ptr, len);
    2804                         if (curstream->codec->channels)
    2805                         {
    2806                             currentTrack[kTrackTypeAudio] = -1;
    2807                             selectedTrack[kTrackTypeAudio]
    2808                                 .av_stream_index = -1;
    2809                             audIdx = -1;
    2810                             AutoSelectAudioTrack();
    2811                             audIdx = selectedTrack[kTrackTypeAudio]
    2812                                 .av_stream_index;
    2813                         }
     2931
     2932                        reselectAudioTrack |= curstream->codec->channels;
    28142933                    }
    28152934
     2935                    if (reselectAudioTrack)
     2936                    {
     2937                        QMutexLocker locker(&avcodeclock);
     2938                        currentTrack[kTrackTypeAudio] = -1;
     2939                        selectedTrack[kTrackTypeAudio]
     2940                            .av_stream_index = -1;
     2941                        audIdx = -1;
     2942                        audSubIdx = -1;
     2943                        AutoSelectAudioTrack();
     2944                        audIdx = selectedTrack[kTrackTypeAudio]
     2945                            .av_stream_index;
     2946                        audSubIdx = selectedTrack[kTrackTypeAudio]
     2947                            .av_substream_index;
     2948                    }
     2949
    28162950                    if (firstloop && pkt->pts != (int64_t)AV_NOPTS_VALUE)
    28172951                        lastapts = (long long)(av_q2d(curstream->time_base) *
    28182952                                               pkt->pts * 1000);
     
    28953029                            .arg(pkt->pts).arg(pkt->dts).arg(temppts)
    28963030                                                        .arg(lastapts));
    28973031
     3032                    if (audSubIdx != -1)
     3033                    {
     3034                        filter_audio_data(audSubIdx, &audioOut,
     3035                                          (char *)audioSamples, data_size);
     3036                    }
     3037
    28983038                    GetNVP()->AddAudioData((char *)audioSamples, data_size,
    28993039                                           temppts);
    29003040
  • libs/libmythtv/decoderbase.h

     
    1717class StreamInfo
    1818{
    1919  public:
    20     StreamInfo() : av_stream_index(-1), language(-2), language_index(0),
     20    StreamInfo() :
     21        av_stream_index(-1), av_substream_index(-1),
     22        language(-2), language_index(0),
    2123        stream_id(-1), easy_reader(false), wide_aspect_ratio(false) {}
    2224    StreamInfo(int a, int b, uint c, int d, bool e = false, bool f = false) :
    23         av_stream_index(a), language(b), language_index(c), stream_id(d),
     25        av_stream_index(a), av_substream_index(-1),
     26        language(b), language_index(c), stream_id(d),
    2427        easy_reader(e), wide_aspect_ratio(f) {}
     28    StreamInfo(int a, int b, uint c, int d, int e,
     29               bool f = false, bool g = false) :
     30        av_stream_index(a), av_substream_index(e),
     31        language(b), language_index(c), stream_id(d),
     32        easy_reader(f), wide_aspect_ratio(g) {}
    2533
    2634  public:
    2735    int  av_stream_index;
     36    // -1 = no substream, 0 for first dual audio stream, 1 for second
     37    int  av_substream_index;
    2838    int  language; ///< ISO639 canonical language key
    2939    uint language_index;
    3040    int  stream_id;