Ticket #5866: mpegrecorder-hdpvr-v1.1.patch
File mpegrecorder-hdpvr-v1.1.patch, 18.1 KB (added by , 15 years ago) |
---|
-
libs/libmythtv/mpegrecorder.h
80 80 uint GetFilteredAudioLayer(void) const; 81 81 uint GetFilteredAudioBitRate(uint audio_layer) const; 82 82 83 void RestartEncoding(void); 83 84 bool StartEncoding(int fd); 84 85 bool StopEncoding(int fd); 85 86 86 87 void ResetForNewFile(void); 87 88 89 bool WaitFor_HDPVR(void); 88 90 void HandleResolutionChanges(void); 89 91 90 92 inline bool CheckCC(uint pid, uint cc); … … 104 106 // State 105 107 bool recording; 106 108 bool encoding; 107 bool needs_resolution;108 109 mutable QMutex start_stop_encoding_lock; 109 110 QMutex recording_wait_lock; 110 111 QWaitCondition recording_wait; … … 113 114 bool cleartimeonpause; 114 115 115 116 // Encoding info 116 int width, height;117 uint width, height; 117 118 int bitrate, maxbitrate, streamtype, aspectratio; 118 119 int audtype, audsamplerate, audbitratel1, audbitratel2, audbitratel3; 119 120 int audvolume; -
libs/libmythtv/mpegrecorder.cpp
19 19 #include <sys/stat.h> 20 20 #include <sys/ioctl.h> 21 21 #include <sys/time.h> 22 #include <sys/poll.h> 22 23 23 24 // avlib headers 24 25 extern "C" { … … 86 87 requires_special_pause(false), 87 88 // State 88 89 recording(false), encoding(false), 89 needs_resolution(false),start_stop_encoding_lock(QMutex::Recursive),90 start_stop_encoding_lock(QMutex::Recursive), 90 91 recording_wait_lock(), recording_wait(), 91 92 // Pausing state 92 93 cleartimeonpause(false), … … 487 488 488 489 bool MpegRecorder::SetFormat(int chanfd) 489 490 { 491 uint idx; 490 492 struct v4l2_format vfmt; 491 493 bzero(&vfmt, sizeof(vfmt)); 492 494 493 495 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 494 496 495 if (ioctl(chanfd, VIDIOC_G_FMT, &vfmt) < 0)497 for (idx = 0; idx < 20; ++idx) 496 498 { 499 if (ioctl(chanfd, VIDIOC_G_FMT, &vfmt) == 0) 500 break; 501 usleep(100 * 1000); 502 } 503 504 if (idx == 10) 505 { 497 506 VERBOSE(VB_IMPORTANT, LOC_ERR + "Error getting format" + ENO); 498 507 return false; 499 508 } … … 501 510 vfmt.fmt.pix.width = width; 502 511 vfmt.fmt.pix.height = height; 503 512 504 if (ioctl(chanfd, VIDIOC_S_FMT, &vfmt) < 0)513 for (idx = 0; idx < 20; ++idx) 505 514 { 515 if (ioctl(chanfd, VIDIOC_S_FMT, &vfmt) == 0) 516 break; 517 usleep(100 * 1000); 518 } 519 520 if (idx == 20) 521 { 506 522 VERBOSE(VB_IMPORTANT, LOC_ERR + "Error setting format" + ENO); 507 523 return false; 508 524 } … … 513 529 /// Set audio language mode 514 530 bool MpegRecorder::SetLanguageMode(int chanfd) 515 531 { 532 uint idx; 516 533 struct v4l2_tuner vt; 517 534 bzero(&vt, sizeof(struct v4l2_tuner)); 518 if (ioctl(chanfd, VIDIOC_G_TUNER, &vt) < 0) 535 536 for (idx = 0; idx < 20; ++idx) 519 537 { 538 if (ioctl(chanfd, VIDIOC_G_TUNER, &vt) == 0) 539 break; 540 usleep(100 * 1000); 541 } 542 543 if (idx == 20) 544 { 520 545 VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to get audio mode" + ENO); 521 546 return false; 522 547 } … … 549 574 success = false; 550 575 } 551 576 552 if (ioctl(chanfd, VIDIOC_S_TUNER, &vt) < 0)577 for (idx = 0; idx < 20; ++idx) 553 578 { 579 if (ioctl(chanfd, VIDIOC_S_TUNER, &vt) == 0) 580 break; 581 usleep(100 * 1000); 582 } 583 584 if (idx == 20) 585 { 554 586 VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to set audio mode" + ENO); 555 587 success = false; 556 588 } … … 561 593 bool MpegRecorder::SetRecordingVolume(int chanfd) 562 594 { 563 595 // Get volume min/max values 596 uint idx; 564 597 struct v4l2_queryctrl qctrl; 565 598 qctrl.id = V4L2_CID_AUDIO_VOLUME; 566 if (ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl) < 0) 599 600 for (idx = 0; idx < 20; ++idx) 567 601 { 602 if (ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl) == 0) 603 break; 604 usleep(100 * 1000); 605 } 606 607 if (idx == 20) 608 { 568 609 VERBOSE(VB_IMPORTANT, LOC_WARN + 569 610 "Unable to get recording volume parameters(max/min)" + ENO + 570 611 "\n\t\t\tusing default range [0,65535]."); … … 582 623 ctrl.id = V4L2_CID_AUDIO_VOLUME; 583 624 ctrl.value = ctrl_volume; 584 625 585 if (ioctl(chanfd, VIDIOC_S_CTRL, &ctrl) < 0)626 for (idx = 0; idx < 20; ++idx) 586 627 { 628 if (ioctl(chanfd, VIDIOC_S_CTRL, &ctrl) == 0) 629 break; 630 usleep(100 * 1000); 631 } 632 633 if (idx == 20) 634 { 587 635 VERBOSE(VB_IMPORTANT, LOC_WARN + 588 636 "Unable to set recording volume" + ENO + "\n\t\t\t" + 589 637 "If you are using an AverMedia M179 card this is normal."); … … 765 813 766 814 for (uint i = 0; i < ext_ctrls.size(); i++) 767 815 { 816 uint idx; 768 817 struct v4l2_ext_controls ctrls; 769 818 bzero(&ctrls, sizeof(struct v4l2_ext_controls)); 770 819 … … 774 823 ctrls.count = 1; 775 824 ctrls.controls = &ext_ctrls[i]; 776 825 777 if (ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)826 for (idx = 0; idx < 20; ++idx) 778 827 { 828 if (ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls) == 0) 829 break; 830 usleep(100 * 1000); 831 } 832 833 if (idx == 20) 834 { 779 835 QMutexLocker locker(&control_description_lock); 780 836 VERBOSE(VB_IMPORTANT, QString("mpegrecorder.cpp:set_ctrls(): ") + 781 837 QString("Could not set %1 to %2") … … 814 870 { 815 871 maxbitrate = high_mpeg4peakbitrate; 816 872 bitrate = high_mpeg4avgbitrate; 873 874 // query supported audio codecs and prefer AC3 875 uint idx; 876 struct v4l2_queryctrl qctrl; 877 qctrl.id = V4L2_CID_MPEG_AUDIO_ENCODING; 878 879 for (idx = 0; idx < 20; ++idx) 880 { 881 if (ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl) == 0) 882 break; 883 usleep(100 * 1000); 884 } 885 886 if (idx == 20) 887 { 888 VERBOSE(VB_IMPORTANT, LOC_WARN + 889 "Unable to get supported audio codecs." + ENO); 890 } 891 else 892 { 893 if (qctrl.minimum != qctrl.maximum) 894 add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_ENCODING, 895 qctrl.maximum); 896 } 817 897 } 818 898 maxbitrate = std::max(maxbitrate, bitrate); 819 899 … … 837 917 int audioinput = audiodevice.toUInt(&ok); 838 918 if (ok) 839 919 { 920 uint idx; 840 921 struct v4l2_audio ain; 841 922 bzero(&ain, sizeof(ain)); 842 923 ain.index = audioinput; 843 if (ioctl(chanfd, VIDIOC_ENUMAUDIO, &ain) < 0) 924 925 for (idx = 0; idx < 20; ++idx) 844 926 { 927 if (ioctl(chanfd, VIDIOC_ENUMAUDIO, &ain) == 0) 928 break; 929 usleep(100 * 1000); 930 } 931 932 if (idx == 20) 933 { 845 934 VERBOSE(VB_IMPORTANT, LOC_WARN + 846 935 "Unable to get audio input."); 847 936 } 848 937 else 849 938 { 850 939 ain.index = audioinput; 851 if (ioctl(chanfd, VIDIOC_S_AUDIO, &ain) < 0) 940 941 for (idx = 0; idx < 20; ++idx) 852 942 { 943 if (ioctl(chanfd, VIDIOC_S_AUDIO, &ain) == 0) 944 break; 945 usleep(100 * 1000); 946 } 947 948 if (idx == 20) 949 { 853 950 VERBOSE(VB_IMPORTANT, LOC_WARN + 854 951 "Unable to set audio input."); 855 952 } … … 1036 1133 if (deviceIsMpegFile) 1037 1134 elapsedTimer.start(); 1038 1135 else if (_device_read_buffer) 1039 _device_read_buffer->Start(); 1136 { 1137 VERBOSE(VB_RECORD, LOC + "Initial startup of recorder"); 1040 1138 1041 needs_resolution = (driver == "hdpvr"); 1139 if (StartEncoding(readfd)) 1140 _device_read_buffer->Start(); 1141 else 1142 { 1143 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to start recording"); 1144 recording = false; 1145 QMutexLocker locker(&recording_wait_lock); 1146 recording_wait.wakeAll(); 1147 _error = true; 1148 } 1149 } 1042 1150 1043 1151 QByteArray vdevice = videodevice.toAscii(); 1044 1152 while (encoding && !_error) 1045 1153 { 1046 1154 if (PauseAndWait(100)) 1047 1155 continue; 1048 1049 HandleResolutionChanges();1050 1156 1051 1157 if (deviceIsMpegFile) 1052 1158 { … … 1090 1196 { 1091 1197 VERBOSE(VB_IMPORTANT, LOC_ERR + "Device error detected"); 1092 1198 1093 _device_read_buffer->Stop(); 1094 1095 QMutexLocker locker(&start_stop_encoding_lock); 1096 1097 StopEncoding(readfd); 1098 1099 // Make sure the next things in the file are a PAT & PMT 1100 if (_stream_data->PATSingleProgram() && 1101 _stream_data->PMTSingleProgram()) 1102 { 1103 bool tmp = _wait_for_keyframe_option; 1104 _wait_for_keyframe_option = false; 1105 HandleSingleProgramPAT(_stream_data->PATSingleProgram()); 1106 HandleSingleProgramPMT(_stream_data->PMTSingleProgram()); 1107 _wait_for_keyframe_option = tmp; 1108 } 1109 1110 if (StartEncoding(readfd)) 1111 { 1112 _device_read_buffer->Start(); 1113 } 1114 else 1115 { 1116 if (0 != close(readfd)) 1117 VERBOSE(VB_IMPORTANT, LOC_ERR + "Close error" + ENO); 1118 1119 // Force card to be reopened on next iteration.. 1120 readfd = -1; 1121 } 1199 RestartEncoding(); 1122 1200 } 1123 1201 else if (_device_read_buffer->IsEOF()) 1124 1202 { … … 1216 1294 } 1217 1295 } 1218 1296 1297 VERBOSE(VB_RECORD, LOC + "StartRecording finishing up"); 1298 1219 1299 if (_device_read_buffer) 1220 1300 { 1221 1301 if (_device_read_buffer->IsRunning()) … … 1224 1304 delete _device_read_buffer; 1225 1305 _device_read_buffer = NULL; 1226 1306 } 1307 1227 1308 StopEncoding(readfd); 1228 1309 1229 1310 FinishRecording(); … … 1373 1454 1374 1455 if (!paused) 1375 1456 { 1457 VERBOSE(VB_RECORD, LOC + "PauseAndWait pause"); 1458 1459 // Some drivers require streaming to be disabled before 1460 // an input switch and other channel format setting. 1461 if (requires_special_pause) 1462 StopEncoding(readfd); 1463 1376 1464 if (_device_read_buffer) 1377 1465 { 1378 1466 QMutex drb_lock; 1379 1467 drb_lock.lock(); 1380 1381 1468 _device_read_buffer->SetRequestPause(true); 1382 1383 1469 pauseWait.wait(&drb_lock, timeout); 1384 1470 } 1385 1471 else 1386 {1387 paused = true;1388 1472 pauseWait.wakeAll(); 1389 }1390 1473 1391 // Some drivers require streaming to be disabled before 1392 // an input switch and other channel format setting. 1393 if (requires_special_pause) 1394 StopEncoding(readfd); 1395 1474 paused = true; 1396 1475 if (tvrec) 1397 1476 tvrec->RecorderPaused(); 1398 1477 } 1399 1478 1400 1479 unpauseWait.wait(&waitlock, timeout); 1401 1480 } 1402 if (!request_pause) 1481 1482 if (!request_pause && paused) 1403 1483 { 1404 if (paused) 1484 VERBOSE(VB_RECORD, LOC + "PauseAndWait unpause"); 1485 1486 if (driver == "hdpvr") 1405 1487 { 1406 // Some drivers require streaming to be disabled before 1407 // an input switch and other channel format setting. 1408 if (requires_special_pause) 1409 StartEncoding(readfd); 1488 m_h264_parser.Reset(); 1489 _wait_for_keyframe_option = true; 1490 _seen_sps = false; 1410 1491 1411 if (_device_read_buffer) 1412 _device_read_buffer->SetRequestPause(false); 1492 // Sleep any less than 1.5 seconds, and the HD-PVR will 1493 // return the old resolution, when the resolution is changing. 1494 usleep(1500 * 1000); 1495 } 1413 1496 1414 if (_stream_data) 1415 _stream_data->Reset(_stream_data->DesiredProgram()); 1416 } 1497 // Some drivers require streaming to be disabled before 1498 // an input switch and other channel format setting. 1499 if (requires_special_pause) 1500 StartEncoding(readfd); 1501 1502 if (_device_read_buffer) 1503 _device_read_buffer->SetRequestPause(false); 1504 1505 if (_stream_data) 1506 _stream_data->Reset(_stream_data->DesiredProgram()); 1507 1417 1508 paused = false; 1418 1509 } 1510 1419 1511 return paused; 1420 1512 } 1421 1513 1514 void MpegRecorder::RestartEncoding(void) 1515 { 1516 VERBOSE(VB_RECORD, LOC + "RestartEncoding"); 1517 1518 _device_read_buffer->Stop(); 1519 1520 QMutexLocker locker(&start_stop_encoding_lock); 1521 1522 StopEncoding(readfd); 1523 1524 // Make sure the next things in the file are a PAT & PMT 1525 if (_stream_data->PATSingleProgram() && 1526 _stream_data->PMTSingleProgram()) 1527 { 1528 _wait_for_keyframe_option = false; 1529 HandleSingleProgramPAT(_stream_data->PATSingleProgram()); 1530 HandleSingleProgramPMT(_stream_data->PMTSingleProgram()); 1531 } 1532 1533 if (StartEncoding(readfd)) 1534 { 1535 _device_read_buffer->Start(); 1536 } 1537 else 1538 { 1539 if (0 != close(readfd)) 1540 VERBOSE(VB_IMPORTANT, LOC_ERR + "Close error" + ENO); 1541 1542 readfd = -1; 1543 } 1544 } 1545 1422 1546 bool MpegRecorder::StartEncoding(int fd) 1423 1547 { 1424 1548 QMutexLocker locker(&start_stop_encoding_lock); … … 1427 1551 memset(&command, 0, sizeof(struct v4l2_encoder_cmd)); 1428 1552 command.cmd = V4L2_ENC_CMD_START; 1429 1553 1554 if (driver == "hdpvr") 1555 HandleResolutionChanges(); 1556 1430 1557 VERBOSE(VB_RECORD, LOC + "StartEncoding"); 1431 needs_resolution = (driver == "hdpvr");1432 1558 1433 for (int idx = 0; idx < 10; ++idx)1559 for (int idx = 0; idx < 20; ++idx) 1434 1560 { 1435 1561 if (ioctl(fd, VIDIOC_ENCODER_CMD, &command) == 0) 1436 1562 { 1563 if (driver == "hdpvr") 1564 { 1565 m_h264_parser.Reset(); 1566 _wait_for_keyframe_option = true; 1567 _seen_sps = false; 1568 } 1569 1437 1570 VERBOSE(VB_RECORD, LOC + "Encoding started"); 1438 1571 return true; 1439 1572 } … … 1444 1577 return false; 1445 1578 } 1446 1579 1447 usleep( 250 * 1000);1580 usleep(100 * 1000); 1448 1581 } 1449 1582 1450 1583 VERBOSE(VB_IMPORTANT, LOC_ERR + "StartEncoding - giving up" + ENO); … … 1461 1594 1462 1595 VERBOSE(VB_RECORD, LOC + "StopEncoding"); 1463 1596 1464 for (int idx = 0; idx < 10; ++idx)1597 for (int idx = 0; idx < 20; ++idx) 1465 1598 { 1466 1467 1599 if (ioctl(fd, VIDIOC_ENCODER_CMD, &command) == 0) 1468 1600 { 1469 1601 VERBOSE(VB_RECORD, LOC + "Encoding stopped"); … … 1476 1608 return false; 1477 1609 } 1478 1610 1479 usleep( 250 * 1000);1611 usleep(100 * 1000); 1480 1612 } 1481 1613 1482 1614 VERBOSE(VB_IMPORTANT, LOC_ERR + "StopEncoding - giving up" + ENO); … … 1544 1676 void MpegRecorder::HandleSingleProgramPMT(ProgramMapTable *pmt) 1545 1677 { 1546 1678 if (!pmt) 1547 {1679 { 1548 1680 return; 1549 1681 } 1550 1682 … … 1564 1696 DTVRecorder::BufferedWrite(*(reinterpret_cast<TSPacket*>(&buf[i]))); 1565 1697 } 1566 1698 1699 bool MpegRecorder::WaitFor_HDPVR(void) 1700 { 1701 // After a resolution change, it can take the HD-PVR a few 1702 // seconds before it is usable again. 1703 1704 // Tell it to start encoding, then wait for it to actually feed us 1705 // some data. 1706 QMutexLocker locker(&start_stop_encoding_lock); 1707 1708 struct v4l2_encoder_cmd command; 1709 struct pollfd polls; 1710 int idx; 1711 1712 memset(&command, 0, sizeof(struct v4l2_encoder_cmd)); 1713 command.cmd = V4L2_ENC_CMD_START; 1714 1715 for (idx = 0; idx < 20; ++idx) 1716 { 1717 if (ioctl(readfd, VIDIOC_ENCODER_CMD, &command) == 0) 1718 break; 1719 usleep(100 * 1000); 1720 } 1721 1722 if (idx == 20) 1723 return false; 1724 1725 polls.fd = readfd; 1726 polls.events = POLLIN; 1727 polls.revents = 0; 1728 1729 for (idx = 0; idx < 10; ++idx) 1730 { 1731 if (poll(&polls, 1, 250) > 0) 1732 break; 1733 } 1734 1735 if (idx == 10) 1736 return false; 1737 1738 // HD-PVR should now be "ready" 1739 command.cmd = V4L2_ENC_CMD_STOP; 1740 1741 for (idx = 0; idx < 20; ++idx) 1742 { 1743 if (ioctl(readfd, VIDIOC_ENCODER_CMD, &command) == 0) 1744 return true; 1745 usleep(100 * 1000); 1746 } 1747 1748 return false; 1749 } 1750 1567 1751 void MpegRecorder::HandleResolutionChanges(void) 1568 1752 { 1569 if (!needs_resolution)1570 return;1571 1572 1753 VERBOSE(VB_RECORD, LOC + "Checking Resolution"); 1573 1754 struct v4l2_format vfmt; 1574 1755 memset(&vfmt, 0, sizeof(vfmt)); 1575 1756 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1576 1757 1758 if (driver == "hdpvr") 1759 WaitFor_HDPVR(); 1760 1761 uint idx; 1577 1762 uint pix = 0; 1763 1764 for (idx = 0; idx < 20; ++idx) 1765 { 1578 1766 if (0 == ioctl(chanfd, VIDIOC_G_FMT, &vfmt)) 1579 1767 { 1580 1768 VERBOSE(VB_RECORD, LOC + QString("Got Resolution %1x%2") 1581 1769 .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height)); 1582 1770 pix = vfmt.fmt.pix.width * vfmt.fmt.pix.height; 1583 needs_resolution = false; 1771 break; 1772 } 1773 // Typically takes 0.9 seconds after a resolution change 1774 usleep(100 * 1000); 1584 1775 } 1585 1776 1586 1777 if (!pix) 1778 { 1779 VERBOSE(VB_RECORD, LOC + "Giving up detecting resolution"); 1587 1780 return; // nothing to do, we don't have a resolution yet 1781 } 1588 1782 1589 1783 int old_max = maxbitrate, old_avg = bitrate; 1590 1784 if (pix <= 768*568) … … 1609 1803 if (old_max == old_avg) 1610 1804 { 1611 1805 VERBOSE(VB_RECORD, LOC + 1612 QString("Old bitrate %1 CBR").arg(old_avg)); 1806 QString("Old bitrate %1 CBR for %2x%3") 1807 .arg(old_avg).arg(width).arg(height)); 1613 1808 } 1614 1809 else 1615 1810 { 1616 1811 VERBOSE(VB_RECORD, LOC + 1617 QString("Old bitrate %1/%2 VBR ")1618 .arg(old_avg).arg(old_max) );1812 QString("Old bitrate %1/%2 VBR for %3x%4") 1813 .arg(old_avg).arg(old_max).arg(width).arg(height)); 1619 1814 } 1620 1815 1621 1816 if (maxbitrate == bitrate) … … 1642 1837 maxbitrate * 1000); 1643 1838 1644 1839 set_ctrls(readfd, ext_ctrls); 1840 1645 1841 } 1646 1647 // Restart streaming. Shouldn't be needed? seems to be with current driver.1648 QMutexLocker locker(&start_stop_encoding_lock);1649 StopEncoding(readfd);1650 StartEncoding(readfd);1651 1652 needs_resolution = false;1653 1842 }