Ticket #2439: 2439-v2.patch
File 2439-v2.patch, 10.6 KB (added by , 19 years ago) |
---|
-
libs/libmythtv/avformatdecoder.cpp
1488 1488 lang_indx = lang_aud_cnt[lang]; 1489 1489 lang_aud_cnt[lang]++; 1490 1490 } 1491 tracks[kTrackTypeAudio].push_back(1492 StreamInfo(i, lang, lang_indx, ic->streams[i]->id));1493 1491 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 1494 1505 VERBOSE(VB_AUDIO, LOC + QString( 1495 1506 "Audio Track #%1 is A/V stream #%2 " 1496 1507 "and has %3 channels in the %4 language(%5).") … … 1555 1566 return scanerror; 1556 1567 } 1557 1568 1569 /** \fn AvFormatDecoder::SetupAudioStreamSubIndexes(bool, bool) 1570 * \brief Reacts to DUAL/STEREO changes on the fly and fix streams. 1571 * 1572 * This function should be called when a switch between dual and 1573 * stereo mpeg audio is detected. Such changes can and will happen at 1574 * any time. 1575 * 1576 * After this method returns, a new audio stream should be selected 1577 * using AvFormatDecoder::autoSelectSubtitleTrack(). 1578 * 1579 * \param index av_stream_index of the stream that has changed 1580 */ 1581 void AvFormatDecoder::SetupAudioStreamSubIndexes(int streamIndex) 1582 { 1583 QMutexLocker locker(&avcodeclock); 1584 1585 // Find the position of the streaminfo in tracks[kTrackTypeAudio] 1586 sinfo_vec_t::iterator current = tracks[kTrackTypeAudio].begin(); 1587 for (; current != tracks[kTrackTypeAudio].end(); ++current) 1588 { 1589 if (current->av_stream_index == streamIndex) 1590 break; 1591 } 1592 if (current == tracks[kTrackTypeAudio].end()) { 1593 VERBOSE(VB_IMPORTANT, LOC 1594 <<"Warning: invalid stream index passed to " 1595 <<"SetupAudioStreamSubIndexes: " 1596 <<streamIndex); 1597 return; 1598 } 1599 1600 // Remove the extra substream or duplicate the current substream 1601 sinfo_vec_t::iterator next = current + 1; 1602 if (current->av_substream_index == -1) { 1603 // Split stream in two (Language I + Language II) 1604 StreamInfo lang1 = *current; 1605 StreamInfo lang2 = *current; 1606 lang1.av_substream_index = 0; 1607 lang2.av_substream_index = 1; 1608 *current = lang1; 1609 tracks[kTrackTypeAudio].insert(next, lang2); 1610 } 1611 else 1612 { 1613 if (next == tracks[kTrackTypeAudio].end() || 1614 next->av_stream_index != streamIndex) { 1615 VERBOSE(VB_IMPORTANT, LOC 1616 <<"Warning: expected substream 1 (Language I) of stream " 1617 << streamIndex 1618 << " following substream 0, found end of list or another stream"); 1619 return; 1620 } 1621 1622 // Remove extra stream info 1623 StreamInfo stream = *current; 1624 stream.av_substream_index = -1; 1625 *current = stream; 1626 tracks[kTrackTypeAudio].erase(next); 1627 } 1628 } 1629 1558 1630 int get_avf_buffer(struct AVCodecContext *c, AVFrame *pic) 1559 1631 { 1560 1632 AvFormatDecoder *nd = (AvFormatDecoder *)(c->opaque); … … 2368 2440 * preference: 2369 2441 * 2370 2442 * 1) The stream last selected by the user, which is 2371 * recalled as the Nth stream in the preferred language. 2443 * recalled as the Nth stream in the preferred language 2444 * or the Nth substream when audio is in dual language 2445 * format (each channel contains a different language track) 2372 2446 * If it can not be located we attempt to find a stream 2373 2447 * in the same language. 2374 2448 * … … 2435 2509 int selTrack = (1 == numStreams) ? 0 : -1; 2436 2510 int wlang = wtrack.language; 2437 2511 2512 if (selTrack < 0 && wtrack.av_substream_index >= 0) 2513 { 2514 VERBOSE(VB_AUDIO, LOC + "Trying to reselect audio sub-stream"); 2515 // Dual stream without language information: choose 2516 // the previous substream that was kept in wtrack, 2517 // ignoring the stream index (which might have changed). 2518 int substream_index = wtrack.av_substream_index; 2519 2520 for (uint i = 0; i < numStreams; i++) 2521 { 2522 if (atracks[i].av_substream_index == substream_index) 2523 { 2524 selTrack = i; 2525 break; 2526 } 2527 } 2528 } 2529 2438 2530 if ((selTrack < 0) && wlang >= -1 && numStreams) 2439 2531 { 2440 2532 VERBOSE(VB_AUDIO, LOC + "Trying to reselect audio track"); … … 2515 2607 return selTrack; 2516 2608 } 2517 2609 2610 static void filter_audio_data(int channel, AudioInfo *audioInfo, 2611 char *buffer, int bufsize) 2612 { 2613 // Only stereo -> mono (left or right) is supported 2614 if (audioInfo->channels != 2) 2615 return; 2616 2617 if (channel != 0 && channel != 1) 2618 return; 2619 2620 const int samplesize = audioInfo->sample_size; 2621 const int samples = bufsize / samplesize; 2622 const int halfsample = samplesize/2; 2623 2624 const char *from; 2625 char *to; 2626 2627 if (channel==0) 2628 { 2629 from = buffer; 2630 to = buffer + halfsample; 2631 } 2632 else 2633 { 2634 from = buffer + halfsample; 2635 to = buffer; 2636 } 2637 2638 for (int sample = 0; sample < samples; 2639 (sample++), (from += samplesize), (to += samplesize)) 2640 { 2641 for(int bit = 0; bit < halfsample; bit++) 2642 to[bit] = from[bit]; 2643 } 2644 } 2645 2518 2646 bool AvFormatDecoder::GetFrame(int onlyvideo) 2519 2647 { 2520 2648 AVPacket *pkt = NULL; … … 2783 2911 avcodeclock.lock(); 2784 2912 int ctype = curstream->codec->codec_type; 2785 2913 int audIdx = selectedTrack[kTrackTypeAudio].av_stream_index; 2914 int audSubIdx = selectedTrack[kTrackTypeAudio].av_substream_index; 2786 2915 int subIdx = selectedTrack[kTrackTypeSubtitle].av_stream_index; 2787 2916 avcodeclock.unlock(); 2788 2917 … … 2792 2921 { 2793 2922 case CODEC_TYPE_AUDIO: 2794 2923 { 2924 bool reselectAudioTrack = false; 2925 2926 // detect switches between stereo and dual languages 2927 bool wasDual = audSubIdx != -1; 2928 bool isDual = curstream->codec->avcodec_dual_language; 2929 if ((wasDual && !isDual) || (!wasDual && isDual)) 2930 { 2931 SetupAudioStreamSubIndexes(audIdx); 2932 reselectAudioTrack = true; 2933 } 2934 2795 2935 // detect channels on streams that need 2796 2936 // to be decoded before we can know this 2797 2937 if (!curstream->codec->channels) … … 2801 2941 ret = avcodec_decode_audio( 2802 2942 curstream->codec, audioSamples, 2803 2943 &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 } 2944 2945 reselectAudioTrack |= curstream->codec->channels; 2814 2946 } 2815 2947 2948 if (reselectAudioTrack) 2949 { 2950 QMutexLocker locker(&avcodeclock); 2951 currentTrack[kTrackTypeAudio] = -1; 2952 selectedTrack[kTrackTypeAudio] 2953 .av_stream_index = -1; 2954 audIdx = -1; 2955 audSubIdx = -1; 2956 AutoSelectAudioTrack(); 2957 audIdx = selectedTrack[kTrackTypeAudio] 2958 .av_stream_index; 2959 audSubIdx = selectedTrack[kTrackTypeAudio] 2960 .av_substream_index; 2961 } 2962 2816 2963 if (firstloop && pkt->pts != (int64_t)AV_NOPTS_VALUE) 2817 2964 lastapts = (long long)(av_q2d(curstream->time_base) * 2818 2965 pkt->pts * 1000); … … 2895 3042 .arg(pkt->pts).arg(pkt->dts).arg(temppts) 2896 3043 .arg(lastapts)); 2897 3044 3045 if (audSubIdx != -1) 3046 { 3047 filter_audio_data(audSubIdx, &audioOut, 3048 (char *)audioSamples, data_size); 3049 } 3050 2898 3051 GetNVP()->AddAudioData((char *)audioSamples, data_size, 2899 3052 temppts); 2900 3053 -
libs/libmythtv/decoderbase.h
17 17 class StreamInfo 18 18 { 19 19 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), 21 23 stream_id(-1), easy_reader(false), wide_aspect_ratio(false) {} 22 24 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), 24 27 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) {} 25 33 26 34 public: 27 35 int av_stream_index; 36 // -1 = no substream, 0 for first dual audio stream, 1 for second 37 int av_substream_index; 28 38 int language; ///< ISO639 canonical language key 29 39 uint language_index; 30 40 int stream_id; -
libs/libmythtv/avformatdecoder.h
185 185 void SeekReset(long long, uint skipFrames, bool doFlush, bool discardFrames); 186 186 187 187 bool SetupAudioStream(void); 188 void SetupAudioStreamSubIndexes(int streamIndex); 188 189 189 190 /// Update our position map, keyframe distance, and the like. 190 191 /// Called for key frame packets.