Ticket #5443: mpegrecorder-drb.patch
File mpegrecorder-drb.patch, 13.1 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);899 900 if (readfd < 0)901 {902 VERBOSE(VB_IMPORTANT, LOC_ERR +903 QString("Failed to open device '%1'").arg(videodevice));904 continue;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 } 905 970 } 906 971 907 bool has_select = true;908 972 909 #if defined(__FreeBSD__)910 // HACK. FreeBSD PVR150/500 driver doesn't currently support select()911 has_select = false;912 #endif 973 if (_device_read_buffer) 974 { 975 len = _device_read_buffer->Read( 976 &(buffer[remainder]), bufferSize - remainder); 913 977 914 if (has_select) 978 // Check for DRB errors 979 if (_device_read_buffer->IsErrored()) 980 { 981 VERBOSE(VB_IMPORTANT, LOC_ERR + "Device error detected"); 982 if (close(readfd) != 0) 983 VERBOSE(VB_IMPORTANT, LOC_ERR + "Close error" + ENO); 984 985 // Force card to be reopened on next iteration.. 986 // _error = true; 987 readfd = -1; 988 } 989 990 if (_device_read_buffer->IsEOF()) 991 { 992 VERBOSE(VB_IMPORTANT, LOC_ERR + "Device EOF detected"); 993 _error = true; 994 } 995 } 996 else 915 997 { 916 tv.tv_sec = 5; 917 tv.tv_usec = 0; 918 FD_ZERO(&rdset); 919 FD_SET(readfd, &rdset); 998 if (has_select) 999 { 1000 tv.tv_sec = 5; 1001 tv.tv_usec = 0; 1002 FD_ZERO(&rdset); 1003 FD_SET(readfd, &rdset); 920 1004 921 switch (select(readfd + 1, &rdset, NULL, NULL, &tv))922 {923 case -1:1005 switch (select(readfd + 1, &rdset, NULL, NULL, &tv)) 1006 { 1007 case -1: 924 1008 if (errno == EINTR) 925 1009 continue; 926 1010 927 1011 VERBOSE(VB_IMPORTANT, LOC_ERR + "Select error" + ENO); 928 1012 continue; 929 1013 930 case 0:1014 case 0: 931 1015 VERBOSE(VB_IMPORTANT, LOC_ERR + "select timeout - " 932 1016 "driver has stopped responding"); 933 1017 … … 941 1025 942 1026 continue; 943 1027 944 default: break; 1028 default: break; 1029 } 945 1030 } 946 }947 1031 948 len = read(readfd, &(buffer[remainder]), bufferSize - remainder);1032 len = read(readfd, &(buffer[remainder]), bufferSize - remainder); 949 1033 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) 1034 if (len < 0 && !has_select) 962 1035 { 963 len = read(readfd,964 &(buffer[remainder]), bufferSize - remainder);1036 usleep(25 * 1000); 1037 continue; 965 1038 } 966 967 if ( len <= 0)1039 1040 if ((len == 0) && (deviceIsMpegFile)) 968 1041 { 969 encoding = false; 1042 close(readfd); 1043 readfd = open(vdevice.constData(), O_RDONLY); 1044 1045 if (readfd >= 0) 1046 { 1047 len = read(readfd, 1048 &(buffer[remainder]), bufferSize - remainder); 1049 } 1050 1051 if (len <= 0) 1052 { 1053 encoding = false; 1054 continue; 1055 } 1056 } 1057 else if (len < 0 && errno != EAGAIN) 1058 { 1059 VERBOSE(VB_IMPORTANT, 1060 LOC_ERR + QString("error reading from: %1") 1061 .arg(videodevice) + ENO); 970 1062 continue; 971 1063 } 972 1064 } 973 else if (len < 0 && errno != EAGAIN)974 {975 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("error reading from: %1")976 .arg(videodevice) + ENO);977 1065 978 continue; 979 } 980 else if (len > 0) 1066 if (len > 0) 981 1067 { 982 1068 len += remainder; 983 1069 984 1070 if (driver == "hdpvr") { 985 1071 remainder = _stream_data->ProcessData(buffer, len); 986 1072 int start_remain = len - remainder; … … 996 1082 } 997 1083 } 998 1084 1085 if (_device_read_buffer) 1086 { 1087 if (_device_read_buffer->IsRunning()) 1088 _device_read_buffer->Stop(); 1089 1090 delete _device_read_buffer; 1091 _device_read_buffer = NULL; 1092 } 1093 999 1094 FinishRecording(); 1000 1095 1001 1096 delete[] buffer; … … 1095 1190 void MpegRecorder::StopRecording(void) 1096 1191 { 1097 1192 encoding = false; 1193 if (_device_read_buffer) 1194 _device_read_buffer->Stop(); 1098 1195 } 1099 1196 1100 1197 void MpegRecorder::ResetForNewFile(void) … … 1133 1230 if (request_pause) 1134 1231 { 1135 1232 QMutex waitlock; 1233 waitlock.lock(); 1234 1136 1235 if (!paused) 1137 1236 { 1237 if (_device_read_buffer) 1238 { 1239 QMutex drb_lock; 1240 drb_lock.lock(); 1241 1242 _device_read_buffer->SetRequestPause(true); 1243 1244 pauseWait.wait(&drb_lock, timeout); 1245 } 1246 else 1247 { 1248 paused = true; 1249 pauseWait.wakeAll(); 1250 } 1251 1138 1252 // Some drivers require streaming to be disabled before 1139 1253 // an input switch and other channel format setting. 1140 1254 if (requires_special_pause) 1141 1255 StopEncoding(readfd); 1142 1256 1143 paused = true;1144 pauseWait.wakeAll();1145 1257 if (tvrec) 1146 1258 tvrec->RecorderPaused(); 1147 1259 } 1148 waitlock.lock(); 1260 1149 1261 unpauseWait.wait(&waitlock, timeout); 1150 1262 } 1151 1263 if (!request_pause) … … 1157 1269 if (requires_special_pause) 1158 1270 StartEncoding(readfd); 1159 1271 1272 if (_device_read_buffer) 1273 _device_read_buffer->SetRequestPause(false); 1274 1160 1275 if (_stream_data) 1161 1276 _stream_data->Reset(_stream_data->DesiredProgram()); 1162 1277 } … … 1167 1282 1168 1283 bool MpegRecorder::StartEncoding(int fd) 1169 1284 { 1285 int idx; 1286 1287 VERBOSE(VB_RECORD, LOC + "StartEncoding"); 1288 1289 if (driver == "hdpvr") 1290 { 1291 VERBOSE(VB_RECORD, LOC + "Waiting for HD-PVR"); 1292 // Make sure it is ready to stream 1293 struct v4l2_format vfmt; 1294 1295 for (idx = 0; idx < 40; ++idx) 1296 { 1297 bzero(&vfmt, sizeof(vfmt)); 1298 1299 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1300 1301 if (ioctl(chanfd, VIDIOC_G_FMT, &vfmt) == 0) 1302 break; 1303 1304 usleep(250 * 1000); 1305 } 1306 1307 if (idx == 400) 1308 { 1309 VERBOSE(VB_IMPORTANT, LOC_ERR + 1310 "StartEncoding - HD-PVR not ready, giving up" + ENO); 1311 return false; 1312 } 1313 1314 VERBOSE(VB_RECORD, QString("HD-PVR video resolution %1 x %2") 1315 .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height)); 1316 } 1317 1170 1318 struct v4l2_encoder_cmd command; 1171 1319 memset(&command, 0, sizeof(struct v4l2_encoder_cmd)); 1172 1320 command.cmd = V4L2_ENC_CMD_START; 1173 1321 1174 for (i nt idx = 0; idx < 10; ++idx)1322 for (idx = 0; idx < 40; ++idx) 1175 1323 { 1176 1324 if (ioctl(fd, VIDIOC_ENCODER_CMD, &command) == 0) 1325 { 1326 VERBOSE(VB_RECORD, LOC + "Encoding started"); 1177 1327 return true; 1328 } 1178 1329 1179 1330 if (errno != EAGAIN) 1180 1331 { … … 1195 1346 memset(&command, 0, sizeof(struct v4l2_encoder_cmd)); 1196 1347 command.cmd = V4L2_ENC_CMD_STOP; 1197 1348 1349 VERBOSE(VB_RECORD, LOC + "StopEncoding"); 1350 1198 1351 for (int idx = 0; idx < 10; ++idx) 1199 1352 { 1200 1353 1201 1354 if (ioctl(fd, VIDIOC_ENCODER_CMD, &command) == 0) 1355 { 1356 VERBOSE(VB_RECORD, LOC + "Encoding stopped"); 1202 1357 return true; 1358 } 1203 1359 1204 1360 if (errno != EAGAIN) 1205 1361 {