Ticket #5443: mpegrecorder-drb-poll.patch
File mpegrecorder-drb-poll.patch, 13.7 KB (added by , 16 years ago) |
---|
-
libs/libmythtv/mpegrecorder.h
6 6 #include "dtvrecorder.h" 7 7 #include "tspacket.h" 8 8 #include "mpegstreamdata.h" 9 #include "DeviceReadBuffer.h" 9 10 10 11 struct AVFormatContext; 11 12 struct AVPacket; … … 13 14 class MpegRecorder : public DTVRecorder, 14 15 public MPEGSingleProgramStreamListener, 15 16 public TSPacketListener, 16 public TSPacketListenerAV 17 public TSPacketListenerAV, 18 public ReaderPausedCB 17 19 { 18 20 public: 19 21 MpegRecorder(TVRec*); … … 58 60 void HandleSingleProgramPAT(ProgramAssociationTable *pat); 59 61 void HandleSingleProgramPMT(ProgramMapTable *pmt); 60 62 63 // ReaderPausedCB 64 virtual void ReaderPaused(int fd) { paused = true; pauseWait.wakeAll(); } 65 61 66 private: 62 67 bool OpenMpegFileAsInput(void); 63 68 bool OpenV4L2DeviceAsInput(void); … … 116 121 static const char *aspectRatio[]; 117 122 static const unsigned int kBuildBufferMaxSize; 118 123 124 // Buffer device reads 125 DeviceReadBuffer *_device_read_buffer; 126 119 127 // TS 120 128 MPEGStreamData *_stream_data; 121 129 unsigned char _stream_id[0x1fff + 1]; -
libs/libmythtv/mpegrecorder.cpp
95 95 audvolume(80), language(0), 96 96 // Input file descriptors 97 97 chanfd(-1), readfd(-1), 98 _device_read_buffer(NULL), 98 99 // TS packet handling 99 _stream_data(NULL) 100 _stream_data(NULL) 100 101 { 101 102 } 102 103 … … 107 108 108 109 void MpegRecorder::TeardownAll(void) 109 110 { 111 StopRecording(); 112 110 113 if (chanfd >= 0) 111 114 { 112 115 close(chanfd); … … 352 355 .arg(usingv4l2).arg(has_v4l2_vbi).arg(has_buggy_vbi)); 353 356 354 357 355 if ((driver != "hdpvr") && !SetFormat(chanfd)) 358 if (driver == "hdpvr") 359 { 360 struct v4l2_format vfmt; 361 bzero(&vfmt, sizeof(vfmt)); 362 363 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 364 365 if (ioctl(chanfd, VIDIOC_G_FMT, &vfmt) == 0) 366 VERBOSE(VB_RECORD, QString("HD-PVR video resolution %1 x %2") 367 .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height)); 368 else 369 VERBOSE(VB_IMPORTANT, 370 LOC_ERR + "HD-PVR driver did not return video resolution."); 371 } 372 else if (!SetFormat(chanfd)) 356 373 return false; 357 374 358 375 if (driver != "hdpvr") … … 384 401 return false; 385 402 } 386 403 404 if (_device_read_buffer) 405 { 406 if (_device_read_buffer->IsRunning()) 407 _device_read_buffer->Stop(); 408 409 delete _device_read_buffer; 410 _device_read_buffer = NULL; 411 } 412 413 _device_read_buffer = new DeviceReadBuffer(this); 414 415 if (!_device_read_buffer) 416 { 417 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to allocate DRB buffer"); 418 _error = true; 419 return false; 420 } 421 422 if (!_device_read_buffer->Setup(vdevice.constData(), readfd)) 423 { 424 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to allocate DRB buffer"); 425 _error = true; 426 return false; 427 } 428 429 VERBOSE(VB_RECORD, LOC + "DRB ready"); 430 387 431 return true; 388 432 } 389 433 … … 842 886 return; 843 887 } 844 888 889 bool has_select = true; 890 891 #if defined(__FreeBSD__) 892 // HACK. FreeBSD PVR150/500 driver doesn't currently support select() 893 has_select = false; 894 #endif 895 845 896 _start_code = 0xffffffff; 846 897 _last_gop_seen = 0; 847 898 _frames_written_count = 0; … … 877 928 878 929 if (deviceIsMpegFile) 879 930 elapsedTimer.start(); 931 else if (_device_read_buffer) 932 _device_read_buffer->Start(); 880 933 881 934 QByteArray vdevice = videodevice.toAscii(); 882 while (encoding )935 while (encoding && !_error) 883 936 { 884 937 if (PauseAndWait(100)) 885 938 continue; 886 939 887 if ( (deviceIsMpegFile) && (GetFramesWritten()))940 if (deviceIsMpegFile) 888 941 { 889 elapsed = (elapsedTimer.elapsed() / 1000.0) + 1; 890 while ((GetFramesWritten() / elapsed) > 30) 942 if (GetFramesWritten()) 891 943 { 892 usleep(50000);893 944 elapsed = (elapsedTimer.elapsed() / 1000.0) + 1; 945 while ((GetFramesWritten() / elapsed) > 30) 946 { 947 usleep(50000); 948 elapsed = (elapsedTimer.elapsed() / 1000.0) + 1; 949 } 894 950 } 895 951 } 952 else 953 { 954 if (readfd < 0) 955 { 956 if (!Open()) 957 { 958 _error = true; 959 return; 960 } 896 961 897 if (readfd < 0) 898 readfd = open(vdevice.constData(), O_RDWR); 962 if (readfd < 0) 963 { 964 VERBOSE(VB_IMPORTANT, LOC_ERR + 965 QString("Failed to open device '%1'") 966 .arg(videodevice)); 967 continue; 968 } 969 } 970 } 899 971 900 if (readfd < 0) 972 973 if (_device_read_buffer) 901 974 { 902 VERBOSE(VB_IMPORTANT, LOC_ERR + 903 QString("Failed to open device '%1'").arg(videodevice)); 904 continue; 905 } 975 len = _device_read_buffer->Read( 976 &(buffer[remainder]), bufferSize - remainder); 906 977 907 bool has_select = true; 978 // Check for DRB errors 979 if (_device_read_buffer->IsErrored()) 980 { 981 VERBOSE(VB_IMPORTANT, LOC_ERR + "Device error detected"); 908 982 909 #if defined(__FreeBSD__) 910 // HACK. FreeBSD PVR150/500 driver doesn't currently support select() 911 has_select = false; 912 #endif 913 914 if (has_select) 983 _device_read_buffer->Stop(); 984 StopEncoding(readfd); 985 usleep(1000); 986 if (StartEncoding(readfd)) 987 { 988 _device_read_buffer->Start(); 989 // Make sure the next things in the file are a PAT & PMT 990 _wait_for_keyframe_option = false; 991 HandleSingleProgramPAT(_stream_data->PATSingleProgram()); 992 HandleSingleProgramPMT(_stream_data->PMTSingleProgram()); 993 _wait_for_keyframe_option = true; 994 } 995 else 996 { 997 if (close(readfd) != 0) 998 VERBOSE(VB_IMPORTANT, LOC_ERR + "Close error" + ENO); 999 1000 // Force card to be reopened on next iteration.. 1001 readfd = -1; 1002 } 1003 } 1004 else if (_device_read_buffer->IsEOF()) 1005 { 1006 VERBOSE(VB_IMPORTANT, LOC_ERR + "Device EOF detected"); 1007 _error = true; 1008 } 1009 } 1010 else 915 1011 { 916 tv.tv_sec = 5; 917 tv.tv_usec = 0; 918 FD_ZERO(&rdset); 919 FD_SET(readfd, &rdset); 1012 if (has_select) 1013 { 1014 tv.tv_sec = 5; 1015 tv.tv_usec = 0; 1016 FD_ZERO(&rdset); 1017 FD_SET(readfd, &rdset); 920 1018 921 switch (select(readfd + 1, &rdset, NULL, NULL, &tv))922 {923 case -1:1019 switch (select(readfd + 1, &rdset, NULL, NULL, &tv)) 1020 { 1021 case -1: 924 1022 if (errno == EINTR) 925 1023 continue; 926 1024 927 1025 VERBOSE(VB_IMPORTANT, LOC_ERR + "Select error" + ENO); 928 1026 continue; 929 1027 930 case 0:1028 case 0: 931 1029 VERBOSE(VB_IMPORTANT, LOC_ERR + "select timeout - " 932 1030 "driver has stopped responding"); 933 1031 … … 941 1039 942 1040 continue; 943 1041 944 default: break; 1042 default: break; 1043 } 945 1044 } 946 }947 1045 948 len = read(readfd, &(buffer[remainder]), bufferSize - remainder);1046 len = read(readfd, &(buffer[remainder]), bufferSize - remainder); 949 1047 950 if (len < 0 && !has_select) 951 { 952 usleep(25 * 1000); 953 continue; 954 } 955 956 if ((len == 0) && (deviceIsMpegFile)) 957 { 958 close(readfd); 959 readfd = open(vdevice.constData(), O_RDONLY); 960 961 if (readfd >= 0) 1048 if (len < 0 && !has_select) 962 1049 { 963 len = read(readfd,964 &(buffer[remainder]), bufferSize - remainder);1050 usleep(25 * 1000); 1051 continue; 965 1052 } 966 967 if ( len <= 0)1053 1054 if ((len == 0) && (deviceIsMpegFile)) 968 1055 { 969 encoding = false; 1056 close(readfd); 1057 readfd = open(vdevice.constData(), O_RDONLY); 1058 1059 if (readfd >= 0) 1060 { 1061 len = read(readfd, 1062 &(buffer[remainder]), bufferSize - remainder); 1063 } 1064 1065 if (len <= 0) 1066 { 1067 encoding = false; 1068 continue; 1069 } 1070 } 1071 else if (len < 0 && errno != EAGAIN) 1072 { 1073 VERBOSE(VB_IMPORTANT, 1074 LOC_ERR + QString("error reading from: %1") 1075 .arg(videodevice) + ENO); 970 1076 continue; 971 1077 } 972 1078 } 973 else if (len < 0 && errno != EAGAIN)974 {975 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("error reading from: %1")976 .arg(videodevice) + ENO);977 1079 978 continue; 979 } 980 else if (len > 0) 1080 if (len > 0) 981 1081 { 982 1082 len += remainder; 983 1083 984 1084 if (driver == "hdpvr") { 985 1085 remainder = _stream_data->ProcessData(buffer, len); 986 1086 int start_remain = len - remainder; … … 996 1096 } 997 1097 } 998 1098 1099 if (_device_read_buffer) 1100 { 1101 if (_device_read_buffer->IsRunning()) 1102 _device_read_buffer->Stop(); 1103 1104 delete _device_read_buffer; 1105 _device_read_buffer = NULL; 1106 } 1107 999 1108 FinishRecording(); 1000 1109 1001 1110 delete[] buffer; … … 1095 1204 void MpegRecorder::StopRecording(void) 1096 1205 { 1097 1206 encoding = false; 1207 if (_device_read_buffer) 1208 _device_read_buffer->Stop(); 1209 StopEncoding(readfd); 1098 1210 } 1099 1211 1100 1212 void MpegRecorder::ResetForNewFile(void) … … 1133 1245 if (request_pause) 1134 1246 { 1135 1247 QMutex waitlock; 1248 waitlock.lock(); 1249 1136 1250 if (!paused) 1137 1251 { 1252 if (_device_read_buffer) 1253 { 1254 QMutex drb_lock; 1255 drb_lock.lock(); 1256 1257 _device_read_buffer->SetRequestPause(true); 1258 1259 pauseWait.wait(&drb_lock, timeout); 1260 } 1261 else 1262 { 1263 paused = true; 1264 pauseWait.wakeAll(); 1265 } 1266 1138 1267 // Some drivers require streaming to be disabled before 1139 1268 // an input switch and other channel format setting. 1140 1269 if (requires_special_pause) 1141 1270 StopEncoding(readfd); 1142 1271 1143 paused = true;1144 pauseWait.wakeAll();1145 1272 if (tvrec) 1146 1273 tvrec->RecorderPaused(); 1147 1274 } 1148 waitlock.lock(); 1275 1149 1276 unpauseWait.wait(&waitlock, timeout); 1150 1277 } 1151 1278 if (!request_pause) … … 1157 1284 if (requires_special_pause) 1158 1285 StartEncoding(readfd); 1159 1286 1287 if (_device_read_buffer) 1288 _device_read_buffer->SetRequestPause(false); 1289 1160 1290 if (_stream_data) 1161 1291 _stream_data->Reset(_stream_data->DesiredProgram()); 1162 1292 } … … 1167 1297 1168 1298 bool MpegRecorder::StartEncoding(int fd) 1169 1299 { 1300 int idx; 1301 1302 VERBOSE(VB_RECORD, LOC + "StartEncoding"); 1303 1304 if (driver == "hdpvr") 1305 { 1306 VERBOSE(VB_RECORD, LOC + "Waiting for HD-PVR"); 1307 // Make sure it is ready to stream 1308 struct v4l2_format vfmt; 1309 1310 for (idx = 0; idx < 40; ++idx) 1311 { 1312 bzero(&vfmt, sizeof(vfmt)); 1313 1314 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1315 1316 if (ioctl(chanfd, VIDIOC_G_FMT, &vfmt) == 0) 1317 break; 1318 1319 usleep(250 * 1000); 1320 } 1321 1322 if (idx == 400) 1323 { 1324 VERBOSE(VB_IMPORTANT, LOC_ERR + 1325 "StartEncoding - HD-PVR not ready, giving up" + ENO); 1326 return false; 1327 } 1328 1329 VERBOSE(VB_RECORD, QString("HD-PVR video resolution %1 x %2") 1330 .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height)); 1331 } 1332 1170 1333 struct v4l2_encoder_cmd command; 1171 1334 memset(&command, 0, sizeof(struct v4l2_encoder_cmd)); 1172 1335 command.cmd = V4L2_ENC_CMD_START; 1173 1336 1174 for (i nt idx = 0; idx < 10; ++idx)1337 for (idx = 0; idx < 40; ++idx) 1175 1338 { 1176 1339 if (ioctl(fd, VIDIOC_ENCODER_CMD, &command) == 0) 1340 { 1341 VERBOSE(VB_RECORD, LOC + "Encoding started"); 1177 1342 return true; 1343 } 1178 1344 1179 1345 if (errno != EAGAIN) 1180 1346 { … … 1195 1361 memset(&command, 0, sizeof(struct v4l2_encoder_cmd)); 1196 1362 command.cmd = V4L2_ENC_CMD_STOP; 1197 1363 1364 VERBOSE(VB_RECORD, LOC + "StopEncoding"); 1365 1198 1366 for (int idx = 0; idx < 10; ++idx) 1199 1367 { 1200 1368 1201 1369 if (ioctl(fd, VIDIOC_ENCODER_CMD, &command) == 0) 1370 { 1371 VERBOSE(VB_RECORD, LOC + "Encoding stopped"); 1202 1372 return true; 1373 } 1203 1374 1204 1375 if (errno != EAGAIN) 1205 1376 {