Ticket #730: mythtv-dtspassthru.3.patch
| File mythtv-dtspassthru.3.patch, 21.8 KB (added by , 20 years ago) |
|---|
-
configure
334 334 x264="no" 335 335 a52="yes" 336 336 a52bin="no" 337 dts=" no"337 dts="yes" 338 338 pp="yes" 339 339 shared_pp="no" 340 340 mingw32="no" … … 682 682 ;; 683 683 --enable-a52bin) a52bin="yes" 684 684 ;; 685 --enable-dts) dts="yes" ; extralibs="$extralibs -ldts"685 --enable-dts) dts="yes" 686 686 ;; 687 --disable-dts) dts="no" 688 ;; 687 689 --disable-pp) pp="no" 688 690 ;; 689 691 --enable-shared-pp) shared_pp="yes" … … 1920 1922 mandir="${prefix}/man" 1921 1923 fi 1922 1924 1925 if test x"$dts" = x"yes"; then 1926 dts="no" 1927 if has_library libdts ; then 1928 dts="yes" 1929 extralibs="$extralibs -ldts" 1930 fi 1931 fi 1932 1923 1933 if test x"$dvb" = x"yes" ; then 1924 1934 dvb="no" 1925 1935 if test -f "$dvb_path"/linux/dvb/frontend.h ; then … … 2187 2197 echo "ALSA support $audio_alsa" 2188 2198 echo "aRts support $audio_arts" 2189 2199 echo "JACK support $audio_jack" 2200 echo "DTS passthrough $dts" 2190 2201 echo 2191 2202 echo "# Video Output Support" 2192 2203 echo "x11 support $x11" -
libs/libmythtv/avformatdecoder.cpp
8 8 using namespace std; 9 9 10 10 // MythTV headers 11 #include "mythconfig.h" // for CONFIG_DTS 11 12 #include "avformatdecoder.h" 12 13 #include "RingBuffer.h" 13 14 #include "NuppelVideoPlayer.h" … … 39 40 /** Set to zero to allow any number of AC3 channels. */ 40 41 #define MAX_OUTPUT_CHANNELS 2 41 42 43 static int dts_syncinfo(uint8_t *indata_ptr, int *flags, 44 int *sample_rate, int *bit_rate); 45 static int dts_decode_header(uint8_t *indata_ptr, int *rate, 46 int *nblks, int *sfreq); 47 static int encode_frame(bool dts, unsigned char* data, int len, 48 short *samples, int &samples_size); 49 42 50 extern pthread_mutex_t avcodeclock; 43 51 44 52 int get_avf_buffer_xvmc(struct AVCodecContext *c, AVFrame *pic); … … 181 189 // Audio 182 190 audioSamples(new short int[AVCODEC_MAX_AUDIO_FRAME_SIZE]), 183 191 allow_ac3_passthru(false), 192 allow_dts_passthru(false), 184 193 // Audio selection 185 194 wantedAudioStream(), selectedAudioStream(), 186 195 // Subtitle selection … … 197 206 198 207 save_cctc[0] = save_cctc[1] = 0; 199 208 allow_ac3_passthru = gContext->GetNumSetting("AC3PassThru", false); 209 #ifdef CONFIG_DTS 210 allow_dts_passthru = gContext->GetNumSetting("DTSPassThru", false); 211 #endif 200 212 201 213 audioIn.sample_size = -32; // force SetupAudioStream to run once 202 214 } … … 948 960 <<") already open, leaving it alone."); 949 961 } 950 962 assert(enc->codec_id); 963 if (enc->codec_id == CODEC_ID_DTS) 964 { 965 enc->sample_rate = 48000; 966 enc->channels = 2; 967 // enc->bit_rate = what??; 968 } 951 969 bitrate += enc->bit_rate; 952 970 break; 953 971 } … … 1733 1751 return list; 1734 1752 } 1735 1753 1736 vector<int> filter_lang(const sinfo_vec_t &audioStreams, int lang_key)1754 static vector<int> filter_lang(const sinfo_vec_t &audioStreams, int lang_key) 1737 1755 { 1738 1756 vector<int> ret; 1739 1757 … … 1744 1762 return ret; 1745 1763 } 1746 1764 1747 int filter_ac3(const AVFormatContext *ic, 1748 const sinfo_vec_t &audioStreams, 1749 const vector<int> &fs) 1765 static int filter_max_ch(const AVFormatContext *ic, 1766 const sinfo_vec_t &audioStreams, 1767 const vector<int> &fs, 1768 enum CodecID codecId = CODEC_ID_NONE) 1750 1769 { 1751 int selectedTrack = -1;1752 1753 vector<int>::const_iterator it = fs.begin();1754 for (; it != fs.end(); ++it)1755 {1756 const int stream_index = audioStreams[*it].av_stream_index;1757 const AVCodecContext *ctx = ic->streams[stream_index]->codec;1758 if (CODEC_ID_AC3 == ctx->codec_id)1759 {1760 selectedTrack = *it;1761 break;1762 }1763 }1764 1765 return selectedTrack;1766 }1767 1768 int filter_max_ch(const AVFormatContext *ic,1769 const sinfo_vec_t &audioStreams,1770 const vector<int> &fs)1771 {1772 1770 int selectedTrack = -1, max_seen = -1; 1773 1771 1774 1772 vector<int>::const_iterator it = fs.begin(); … … 1776 1774 { 1777 1775 const int stream_index = audioStreams[*it].av_stream_index; 1778 1776 const AVCodecContext *ctx = ic->streams[stream_index]->codec; 1779 if ( max_seen < ctx->channels)1777 if (codecId == CODEC_ID_NONE || codecId == ctx->codec_id) 1780 1778 { 1781 selectedTrack = *it; 1782 max_seen = ctx->channels; 1779 if (max_seen < ctx->channels) 1780 { 1781 selectedTrack = *it; 1782 max_seen = ctx->channels; 1783 } 1783 1784 } 1784 1785 } 1785 1786 … … 1789 1790 /** \fn AvFormatDecoder::autoSelectAudioTrack(void) 1790 1791 * \brief Selects the best audio track. 1791 1792 * 1792 * This function will select the best audio track 1793 * available using the following rules: 1793 * This function will select the best audio track available 1794 * using the following criteria, in order of decreasing 1795 * preference: 1794 1796 * 1795 * First we try to select the stream last selected by the1796 * user, which is recalled as the Nth stream in the1797 * preferred language. If it can not be located we attempt1798 * to find a streamin the same language.1797 * 1) The stream last selected by the user, which is 1798 * recalled as the Nth stream in the preferred language. 1799 * If it can not be located we attempt to find a stream 1800 * in the same language. 1799 1801 * 1800 * If we can not reselect the last user selected stream, 1801 * then for each preferred language from most preferred to 1802 * least preferred, we try to use the first AC3 track found, 1803 * or if no AC3 audio is found then we try to select the 1804 * audio track with the greatest number of audio channels. 1802 * 2) If we can not reselect the last user selected stream, 1803 * then for each preferred language from most preferred 1804 * to least preferred, we try to find a new stream based 1805 * on the algorithm below. 1805 1806 * 1806 * If we can not select a stream in a preferred language 1807 * we try to use the first AC3 track found irrespective 1808 * of language, and if no AC3 audio is found then we try 1809 * to select the audio track with the greatest number of 1810 * audio channels. 1807 * 3) If we can not select a stream in a preferred language 1808 * we try to select a stream irrespective of language 1809 * based on the algorithm below. 1810 * 1811 * When searching for a new stream (ie. options 2 and 3 1812 * above), the following search is carried out in order: 1813 * 1814 * i) If DTS passthrough is enabled then the DTS track with 1815 * the greatest number of audio channels is selected 1816 * (the first will be chosen if there are several the 1817 * same). If DTS passthrough is not enabled this step 1818 * will be skipped because internal DTS decoding is not 1819 * currently supported. 1820 * 1821 * ii) If no DTS track is chosen, the AC3 track with the 1822 * greatest number of audio channels is selected (the 1823 * first will be chosen if there are several the same). 1824 * Internal decoding of AC3 is supported, so this will 1825 * be used irrespective of whether AC3 passthrough is 1826 * enabled. 1827 * 1828 * iii) Lastly the track with the greatest number of audio 1829 * channels irrespective of type will be selected. 1811 1830 * \return true if a track was selected, false otherwise 1812 1831 */ 1813 1832 bool AvFormatDecoder::autoSelectAudioTrack(void) … … 1822 1841 { 1823 1842 int idx = audioStreams[i].av_stream_index; 1824 1843 AVCodecContext *codec_ctx = ic->streams[idx]->codec; 1844 bool do_ac3_passthru = (allow_ac3_passthru && !transcoding && 1845 (codec_ctx->codec_id == CODEC_ID_AC3)); 1846 bool do_dts_passthru = (allow_dts_passthru && !transcoding && 1847 (codec_ctx->codec_id == CODEC_ID_DTS)); 1825 1848 AudioInfo item(codec_ctx->codec_id, 1826 1849 codec_ctx->sample_rate, codec_ctx->channels, 1827 (allow_ac3_passthru && !transcoding && 1828 (codec_ctx->codec_id == CODEC_ID_AC3))); 1850 do_ac3_passthru || do_dts_passthru); 1829 1851 VERBOSE(VB_AUDIO, LOC + " * " + item.toString()); 1830 1852 } 1831 1853 #endif … … 1855 1877 // try to get best track for most preferred language 1856 1878 selectedTrack = -1; 1857 1879 vector<int>::const_iterator it = languagePreference.begin(); 1858 for (; it != languagePreference.end() ; ++it)1880 for (; it != languagePreference.end() && selectedTrack<0; ++it) 1859 1881 { 1860 1882 vector<int> flang = filter_lang(audioStreams, *it); 1861 if ((selectedTrack = filter_ac3(ic, audioStreams, flang)) >= 0) 1862 break; 1863 if ((selectedTrack = filter_max_ch(ic, audioStreams, flang)) >= 0) 1864 break; 1883 if (allow_dts_passthru && !transcoding) 1884 selectedTrack = filter_max_ch(ic, audioStreams, flang, 1885 CODEC_ID_DTS); 1886 if (selectedTrack < 0) 1887 selectedTrack = filter_max_ch(ic, audioStreams, flang, 1888 CODEC_ID_AC3); 1889 if (selectedTrack < 0) 1890 selectedTrack = filter_max_ch(ic, audioStreams, flang); 1865 1891 } 1866 1892 // try to get best track for any language 1867 1893 if (selectedTrack < 0) 1868 1894 { 1869 1895 VERBOSE(VB_AUDIO, LOC + "Trying to select audio track (wo/lang)"); 1870 1896 vector<int> flang = filter_lang(audioStreams, -1); 1871 if ((selectedTrack = filter_ac3(ic, audioStreams, flang)) < 0) 1872 selectedTrack = filter_max_ch(ic, audioStreams, flang); 1897 if (allow_dts_passthru && !transcoding) 1898 selectedTrack = filter_max_ch(ic, audioStreams, flang, 1899 CODEC_ID_DTS); 1900 if (selectedTrack < 0) 1901 selectedTrack = filter_max_ch(ic, audioStreams, flang, 1902 CODEC_ID_AC3); 1903 if (selectedTrack < 0) 1904 selectedTrack = filter_max_ch(ic, audioStreams, flang); 1873 1905 } 1874 1906 } 1875 1907 … … 2282 2314 pthread_mutex_lock(&avcodeclock); 2283 2315 ret = len; 2284 2316 data_size = 0; 2285 if (audioOut.do_ ac3_passthru)2317 if (audioOut.do_passthru) 2286 2318 { 2287 2319 data_size = pkt->size; 2288 ret = EncodeAC3Frame(ptr, len, audioSamples, 2289 data_size); 2320 bool dts = CODEC_ID_DTS == curstream->codec->codec_id; 2321 ret = encode_frame(dts, ptr, len, 2322 audioSamples, data_size); 2290 2323 } 2291 2324 else 2292 2325 { … … 2314 2347 } 2315 2348 pthread_mutex_unlock(&avcodeclock); 2316 2349 2317 ptr += ret;2318 len -= ret;2319 2350 2320 2351 if (data_size <= 0) 2352 { 2353 ptr += ret; 2354 len -= ret; 2321 2355 continue; 2356 } 2322 2357 2323 2358 long long temppts = lastapts; 2324 2359 … … 2516 2551 { 2517 2552 assert(curstream); 2518 2553 assert(curstream->codec); 2519 codec_ctx = curstream->codec; 2554 codec_ctx = curstream->codec; 2520 2555 bool do_ac3_passthru = (allow_ac3_passthru && !transcoding && 2521 2556 (codec_ctx->codec_id == CODEC_ID_AC3)); 2557 bool do_dts_passthru = (allow_dts_passthru && !transcoding && 2558 (codec_ctx->codec_id == CODEC_ID_DTS)); 2522 2559 info = AudioInfo(codec_ctx->codec_id, 2523 2560 codec_ctx->sample_rate, codec_ctx->channels, 2524 do_ac3_passthru );2561 do_ac3_passthru || do_dts_passthru); 2525 2562 } 2526 2563 2527 2564 if (info == audioIn) … … 2531 2568 QString("audio track #%1").arg(currentAudioTrack+1)); 2532 2569 2533 2570 audioOut = audioIn = info; 2534 if (audioIn.do_ ac3_passthru)2571 if (audioIn.do_passthru) 2535 2572 { 2536 2573 // A passthru stream looks like a 48KHz 2ch (@ 16bit) to the sound card 2537 2574 audioOut.channels = 2; … … 2563 2600 return true; 2564 2601 } 2565 2602 2566 int AvFormatDecoder::EncodeAC3Frame(unsigned char *data, int len,2567 short *samples, int &samples_size)2603 static int encode_frame(bool dts, unsigned char *data, int len, 2604 short *samples, int &samples_size) 2568 2605 { 2569 2606 int enc_len; 2570 2607 int flags, sample_rate, bit_rate; … … 2578 2615 // ignore, and if so, may as well just assume that it will ignore 2579 2616 // anything with a bad CRC... 2580 2617 2581 enc_len = a52_syncinfo(data, &flags, &sample_rate, &bit_rate); 2618 uint nr_samples = 0, block_len; 2619 if(dts) 2620 { 2621 enc_len = dts_syncinfo(data, &flags, &sample_rate, &bit_rate); 2622 int rate, sfreq, nblks; 2623 dts_decode_header(data, &rate, &nblks, &sfreq); 2624 nr_samples = nblks * 32; 2625 block_len = nr_samples * 2 * 2; 2626 } 2627 else 2628 { 2629 enc_len = a52_syncinfo(data, &flags, &sample_rate, &bit_rate); 2630 block_len = MAX_AC3_FRAME_SIZE; 2631 } 2582 2632 2583 2633 if (enc_len == 0 || enc_len > len) 2584 2634 { … … 2586 2636 return len; 2587 2637 } 2588 2638 2589 if (enc_len > MAX_AC3_FRAME_SIZE - 8) 2590 enc_len = MAX_AC3_FRAME_SIZE - 8; 2639 enc_len = min((uint)enc_len, block_len - 8); 2591 2640 2592 2641 swab(data, ucsamples + 8, enc_len); 2593 2642 2594 // the following values come from ao_hwac3.c in mplayer.2643 // the following values come from libmpcodecs/ad_hwac3.c in mplayer. 2595 2644 // they form a valid IEC958 AC3 header. 2596 2645 ucsamples[0] = 0x72; 2597 2646 ucsamples[1] = 0xF8; 2598 2647 ucsamples[2] = 0x1F; 2599 2648 ucsamples[3] = 0x4E; 2600 ucsamples[4] = 0x01; 2649 if(dts) 2650 { 2651 switch(nr_samples) 2652 { 2653 case 512: 2654 ucsamples[4] = 0x0B; /* DTS-1 (512-sample bursts) */ 2655 break; 2656 2657 case 1024: 2658 ucsamples[4] = 0x0C; /* DTS-2 (1024-sample bursts) */ 2659 break; 2660 2661 case 2048: 2662 ucsamples[4] = 0x0D; /* DTS-3 (2048-sample bursts) */ 2663 break; 2664 2665 default: 2666 VERBOSE(VB_IMPORTANT, LOC + 2667 QString("DTS: %1-sample bursts not supported") 2668 .arg(nr_samples)); 2669 ucsamples[4] = 0x00; 2670 break; 2671 } 2672 } 2673 else 2674 { 2675 ucsamples[4] = 0x01; 2676 } 2601 2677 ucsamples[5] = 0x00; 2602 2678 ucsamples[6] = (enc_len << 3) & 0xFF; 2603 2679 ucsamples[7] = (enc_len >> 5) & 0xFF; 2604 memset(ucsamples + 8 + enc_len, 0, MAX_AC3_FRAME_SIZE- 8 - enc_len);2605 samples_size = MAX_AC3_FRAME_SIZE;2680 memset(ucsamples + 8 + enc_len, 0, block_len - 8 - enc_len); 2681 samples_size = block_len; 2606 2682 2607 return len; // consume whole frame even if len > enc_len ?2683 return enc_len; 2608 2684 } 2609 2685 2610 2686 void AvFormatDecoder::AddTextData(unsigned char *buf, int len, … … 2612 2688 { 2613 2689 m_parent->AddTextData((char*)buf, len, timecode, type); 2614 2690 } 2691 2692 static int DTS_SAMPLEFREQS[16] = 2693 { 2694 0, 8000, 16000, 32000, 64000, 128000, 11025, 22050, 2695 44100, 88200, 176400, 12000, 24000, 48000, 96000, 192000 2696 }; 2697 2698 static int DTS_BITRATES[30] = 2699 { 2700 32000, 56000, 64000, 96000, 112000, 128000, 2701 192000, 224000, 256000, 320000, 384000, 448000, 2702 512000, 576000, 640000, 768000, 896000, 1024000, 2703 1152000, 1280000, 1344000, 1408000, 1411200, 1472000, 2704 1536000, 1920000, 2048000, 3072000, 3840000, 4096000 2705 }; 2706 2707 static int dts_syncinfo(uint8_t *indata_ptr, int */*flags*/, 2708 int *sample_rate, int *bit_rate) 2709 { 2710 int nblks; 2711 int rate; 2712 int sfreq; 2713 2714 int fsize = dts_decode_header(indata_ptr, &rate, &nblks, &sfreq); 2715 if(fsize >= 0) 2716 { 2717 if(rate >= 0 && rate <= 29) 2718 *bit_rate = DTS_BITRATES[rate]; 2719 else 2720 *bit_rate = 0; 2721 if(sfreq >= 1 && sfreq <= 15) 2722 *sample_rate = DTS_SAMPLEFREQS[sfreq]; 2723 else 2724 *sample_rate = 0; 2725 } 2726 return fsize; 2727 } 2728 2729 static int dts_decode_header(uint8_t *indata_ptr, int *rate, 2730 int *nblks, int *sfreq) 2731 { 2732 uint id = ((indata_ptr[0] << 24) | (indata_ptr[1] << 16) | 2733 (indata_ptr[2] << 8) | (indata_ptr[3])); 2734 2735 if (id != 0x7ffe8001) 2736 return -1; 2737 2738 int ftype = indata_ptr[4] >> 7; 2739 2740 int surp = (indata_ptr[4] >> 2) & 0x1f; 2741 surp = (surp + 1) % 32; 2742 2743 *nblks = (indata_ptr[4] & 0x01) << 6 | (indata_ptr[5] >> 2); 2744 ++*nblks; 2745 2746 int fsize = (indata_ptr[5] & 0x03) << 12 | 2747 (indata_ptr[6] << 4) | (indata_ptr[7] >> 4); 2748 ++fsize; 2749 2750 *sfreq = (indata_ptr[8] >> 2) & 0x0f; 2751 *rate = (indata_ptr[8] & 0x03) << 3 | ((indata_ptr[9] >> 5) & 0x07); 2752 2753 if(ftype != 1) 2754 { 2755 VERBOSE(VB_IMPORTANT, LOC + 2756 QString("DTS: Termination frames not handled (ftype %1)") 2757 .arg(ftype)); 2758 return -1; 2759 } 2760 2761 if(*sfreq != 13) 2762 { 2763 VERBOSE(VB_IMPORTANT, LOC + 2764 QString("DTS: Only 48kHz supported (sfreq %1)").arg(*sfreq)); 2765 return -1; 2766 } 2767 2768 if((fsize > 8192) || (fsize < 96)) 2769 { 2770 VERBOSE(VB_IMPORTANT, LOC + 2771 QString("DTS: fsize: %1 invalid").arg(fsize)); 2772 return -1; 2773 } 2774 2775 if(*nblks != 8 && *nblks != 16 && *nblks != 32 && 2776 *nblks != 64 && *nblks != 128 && ftype == 1) 2777 { 2778 VERBOSE(VB_IMPORTANT, LOC + 2779 QString("DTS: nblks %1 not valid for normal frame") 2780 .arg(*nblks)); 2781 return -1; 2782 } 2783 2784 return fsize; 2785 } -
libs/libmythtv/avformatdecoder.h
38 38 public: 39 39 AudioInfo() : 40 40 codec_id(CODEC_ID_NONE), sample_size(-2), sample_rate(-1), 41 channels(-1), do_ ac3_passthru(false)41 channels(-1), do_passthru(false) 42 42 {;} 43 43 44 AudioInfo(CodecID id, int sr, int ch, bool ac3) :44 AudioInfo(CodecID id, int sr, int ch, bool passthru) : 45 45 codec_id(id), sample_size(ch*2), sample_rate(sr), 46 channels(ch), do_ ac3_passthru(ac3)46 channels(ch), do_passthru(passthru) 47 47 {;} 48 48 49 49 CodecID codec_id; 50 50 int sample_size, sample_rate, channels; 51 bool do_ ac3_passthru;51 bool do_passthru; 52 52 53 53 /// \brief Bits per sample. 54 54 int bps(void) const … … 60 60 { 61 61 return (codec_id==o.codec_id && channels==o.channels && 62 62 sample_size==o.sample_size && sample_rate==o.sample_rate && 63 do_ ac3_passthru==o.do_ac3_passthru);63 do_passthru==o.do_passthru); 64 64 } 65 65 QString toString() const 66 66 { 67 67 return QString("id(%1) %2Hz %3ch %4bps%5") 68 68 .arg(codec_id_string(codec_id),4).arg(sample_rate,5) 69 69 .arg(channels,2).arg(bps(),3) 70 .arg((do_ ac3_passthru) ? "pt":"",3);70 .arg((do_passthru) ? "pt":"",3); 71 71 } 72 72 }; 73 73 … … 143 143 144 144 protected: 145 145 /// Attempt to find the optimal audio stream to use based on the number of channels, 146 /// and if we're doing AC3 passthrough. This will select the highest stream number147 /// that matches our criteria.146 /// and if we're doing AC3/DTS passthrough. This will select the highest stream 147 /// number that matches our criteria. 148 148 bool autoSelectAudioTrack(); 149 149 150 150 bool autoSelectSubtitleTrack(); … … 187 187 188 188 bool SetupAudioStream(void); 189 189 190 int EncodeAC3Frame(unsigned char* data, int len, short *samples,191 int &samples_size);192 193 190 // Update our position map, keyframe distance, and the like. Called for key frame packets. 194 191 void HandleGopStart(AVPacket *pkt); 195 192 … … 238 235 // Audio 239 236 short int *audioSamples; 240 237 bool allow_ac3_passthru; 238 bool allow_dts_passthru; 241 239 242 240 AudioInfo audioIn; 243 241 AudioInfo audioOut; -
libs/libavformat/mpeg.c
88 88 #define AUDIO_ID 0xc0 89 89 #define VIDEO_ID 0xe0 90 90 #define AC3_ID 0x80 91 #define DTS_ID 0x8 a91 #define DTS_ID 0x88 92 92 #define LPCM_ID 0xa0 93 93 #define SUB_ID 0x20 94 94 -
programs/mythfrontend/globalsettings.cpp
133 133 return gc; 134 134 } 135 135 136 #ifdef CONFIG_DTS 137 static HostCheckBox *DTSPassThrough() 138 { 139 HostCheckBox *gc = new HostCheckBox("DTSPassThru"); 140 gc->setLabel(QObject::tr("Enable DTS to SPDIF passthrough")); 141 gc->setValue(false); 142 gc->setHelpText(QObject::tr("Enable sending DTS audio directly to your " 143 "sound card's SPDIF output, on sources which contain " 144 "DTS soundtracks (usually DVDs). Requires that the " 145 "audio output device be set to something suitable.")); 146 return gc; 147 } 148 #endif 149 136 150 static HostCheckBox *Deinterlace() 137 151 { 138 152 HostCheckBox *gc = new HostCheckBox("Deinterlace"); … … 2059 2073 2060 2074 addChild(AudioOutputDevice()); 2061 2075 addChild(AC3PassThrough()); 2076 #ifdef CONFIG_DTS 2077 addChild(DTSPassThrough()); 2078 #endif 2062 2079 addChild(AggressiveBuffer()); 2063 2080 2064 2081 Setting* volumeControl = MythControlsVolume();
