Ticket #2439: 2439-v1.patch
| File 2439-v1.patch, 10.0 KB (added by , 19 years ago) |
|---|
-
libs/libmythtv/avformatdecoder.h
185 185 void SeekReset(long long, uint skipFrames, bool doFlush, bool discardFrames); 186 186 187 187 bool SetupAudioStream(void); 188 bool SetupAudioStreamSubIndexes(bool wasDual, bool isDual); 188 189 189 190 /// Update our position map, keyframe distance, and the like. 190 191 /// Called for key frame packets. -
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 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 */ 1588 bool 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 1558 1622 int get_avf_buffer(struct AVCodecContext *c, AVFrame *pic) 1559 1623 { 1560 1624 AvFormatDecoder *nd = (AvFormatDecoder *)(c->opaque); … … 2368 2432 * preference: 2369 2433 * 2370 2434 * 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) 2372 2438 * If it can not be located we attempt to find a stream 2373 2439 * in the same language. 2374 2440 * … … 2435 2501 int selTrack = (1 == numStreams) ? 0 : -1; 2436 2502 int wlang = wtrack.language; 2437 2503 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 2438 2522 if ((selTrack < 0) && wlang >= -1 && numStreams) 2439 2523 { 2440 2524 VERBOSE(VB_AUDIO, LOC + "Trying to reselect audio track"); … … 2515 2599 return selTrack; 2516 2600 } 2517 2601 2602 static 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 2518 2638 bool AvFormatDecoder::GetFrame(int onlyvideo) 2519 2639 { 2520 2640 AVPacket *pkt = NULL; … … 2783 2903 avcodeclock.lock(); 2784 2904 int ctype = curstream->codec->codec_type; 2785 2905 int audIdx = selectedTrack[kTrackTypeAudio].av_stream_index; 2906 int audSubIdx = selectedTrack[kTrackTypeAudio].av_substream_index; 2786 2907 int subIdx = selectedTrack[kTrackTypeSubtitle].av_stream_index; 2787 2908 avcodeclock.unlock(); 2788 2909 … … 2792 2913 { 2793 2914 case CODEC_TYPE_AUDIO: 2794 2915 { 2916 // detect switches between stereo and dual languages 2917 bool reselectAudioTrack = 2918 SetupAudioStreamSubIndexes( 2919 audSubIdx != -1, 2920 curstream->codec->avcodec_dual_language); 2921 2795 2922 // detect channels on streams that need 2796 2923 // to be decoded before we can know this 2797 2924 if (!curstream->codec->channels) … … 2801 2928 ret = avcodec_decode_audio( 2802 2929 curstream->codec, audioSamples, 2803 2930 &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; 2814 2933 } 2815 2934 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 2816 2950 if (firstloop && pkt->pts != (int64_t)AV_NOPTS_VALUE) 2817 2951 lastapts = (long long)(av_q2d(curstream->time_base) * 2818 2952 pkt->pts * 1000); … … 2895 3029 .arg(pkt->pts).arg(pkt->dts).arg(temppts) 2896 3030 .arg(lastapts)); 2897 3031 3032 if (audSubIdx != -1) 3033 { 3034 filter_audio_data(audSubIdx, &audioOut, 3035 (char *)audioSamples, data_size); 3036 } 3037 2898 3038 GetNVP()->AddAudioData((char *)audioSamples, data_size, 2899 3039 temppts); 2900 3040 -
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;
