Mercurial > pt1.oyama
comparison recpt1/tssplitter_lite.c @ 120:8e438d2a1529
add tiny lipsync code.
author | Naoya OYAMA <naoya.oyama@gmail.com> |
---|---|
date | Sun, 25 Apr 2010 18:26:32 +0900 |
parents | 4e7aaa72e158 |
children | e915d31c5bd9 |
comparison
equal
deleted
inserted
replaced
119:4e7aaa72e158 | 120:8e438d2a1529 |
---|---|
58 static int GetCrc32(unsigned char *data, int len); | 58 static int GetCrc32(unsigned char *data, int len); |
59 static int GetPid(unsigned char *data); | 59 static int GetPid(unsigned char *data); |
60 static int parse_tot( const unsigned char* packet, time_t *t ); | 60 static int parse_tot( const unsigned char* packet, time_t *t ); |
61 void dump_packet( const uint8_t *packet ); | 61 void dump_packet( const uint8_t *packet ); |
62 static int parse_pcr(int64_t *ppcr_high, int *ppcr_low, const uint8_t *packet); | 62 static int parse_pcr(int64_t *ppcr_high, int *ppcr_low, const uint8_t *packet); |
63 //static int parse_pts(int64_t *ppts, int64_t *pdts, const uint8_t *packet, int *len_pes, splitesbuf_t *esbuf, const int pid); | |
64 //static int ts2pes(int64_t *ppts, int64_t *pdts, const uint8_t *packet, splitpesbuf_t *pesbuf, splitesbuf_t *esbuf, const int pid); | |
65 static int DemuxTs(const uint8_t *packet, splitter *sp, const int pid, int *random_access); | 63 static int DemuxTs(const uint8_t *packet, splitter *sp, const int pid, int *random_access); |
66 static int pes2es(splitpesbuf_t *pesbuf, splitesbuf_t *esbuf, const int pid); | 64 static int pes2es(splitpesbuf_t *pesbuf, splitesbuf_t *esbuf, const int pid, int random_access_indicator); |
67 static int64_t get_pts(const uint8_t *p); | 65 static int64_t get_pts(const uint8_t *p); |
68 void search_mpeg_system_header(const uint8_t *p); | 66 void search_mpeg_system_header(const uint8_t *p); |
69 int esbuf_write(splitesbuf_t *esbuf, int pid); | 67 int esbuf_write(splitesbuf_t *esbuf, int pid); |
70 //void forward_stc(timespec *stc, timespec offset); | 68 //void forward_stc(timespec *stc, timespec offset); |
71 // | |
72 | |
73 static int pesbuf_packet_start_code_prefix(splitpesbuf_t *pesbuf); | 69 static int pesbuf_packet_start_code_prefix(splitpesbuf_t *pesbuf); |
74 static int pesbuf_empty(splitpesbuf_t *pesbuf); | 70 static int pesbuf_empty(splitpesbuf_t *pesbuf); |
75 void pesbuf_clear(splitpesbuf_t *pesbuf); | 71 void pesbuf_clear(splitpesbuf_t *pesbuf); |
76 static int pesbuf_add(splitpesbuf_t *pesbuf, const uint8_t *data, int len); | 72 static int pesbuf_add(splitpesbuf_t *pesbuf, const uint8_t *data, int len); |
77 static int esbuf_empty(splitesbuf_t *esbuf); | 73 static int esbuf_empty(splitesbuf_t *esbuf); |
975 *ppcr_high = ((int64_t)v << 1) | (p[4] >> 7); | 971 *ppcr_high = ((int64_t)v << 1) | (p[4] >> 7); |
976 *ppcr_low = ((p[4] & 1) << 8) | p[5]; | 972 *ppcr_low = ((p[4] & 1) << 8) | p[5]; |
977 return 0; | 973 return 0; |
978 } | 974 } |
979 | 975 |
980 #if 0 | |
981 /** | |
982 * TSを解析してPESを出力する | |
983 */ | |
984 static int ts2pes(int64_t *ppts, int64_t *pdts, const uint8_t *packet, splitpesbuf_t *pesbuf, splitesbuf_t *esbuf, const int pid) | |
985 { | |
986 /* 全体的に length がpacket長越えた時の処理を追記すること */ | |
987 /* | |
988 * PES先頭までの長さは | |
989 * 4byte : continity counter | |
990 * 27,28bit が adaptation fileld制御 | |
991 * (01:ペイロードのみ, 10:adaptation fileldのみ、11:adaptation fileld+payload、00:reserved) | |
992 * ペイロード長 = 188 - TS header(4byte) -adaptation field長 -1 | |
993 */ | |
994 int len_afh = 0; | |
995 *ppts = -1; | |
996 *pdts = -1; | |
997 int flags = 0; | |
998 const uint8_t *p; | |
999 p = (uint8_t*)packet; | |
1000 | |
1001 flags = (p[3] & 0x30) >> 4; | |
1002 if ( flags == 0x02 || flags == 0x00) { | |
1003 /* ペイロードなし */ | |
1004 return -1; | |
1005 } else if ( flags == 0x03 ) { | |
1006 /* アダプテーションフィールド+ペイロード */ | |
1007 /* アダプテーションフィールド長 */ | |
1008 len_afh = *(p+LENGTH_TS_HEADER) & 0xff; | |
1009 if ( len_afh > LENGTH_PACKET -LENGTH_TS_HEADER ) { | |
1010 return -1; | |
1011 } | |
1012 if (!(p[1] & 0x40)) { | |
1013 /* payload start unit indicator 発見 */ | |
1014 if ( pesbuf->size != 0 ) { | |
1015 pes2es(ppts, pdts, pesbuf, esbuf, pid); | |
1016 pesbuf->size = 0; | |
1017 } | |
1018 memcpy(pesbuf->buffer + pesbuf->size, | |
1019 packet +LENGTH_TS_HEADER +len_afh +1, | |
1020 LENGTH_PACKET -LENGTH_TS_HEADER -len_afh -1); | |
1021 pesbuf->size += LENGTH_PACKET -LENGTH_TS_HEADER -len_afh -1; | |
1022 } | |
1023 /* PES先頭パケットではないのでバッファに書き込み */ | |
1024 if ( pesbuf->size != 0 ) { | |
1025 memcpy(pesbuf->buffer + pesbuf->size, | |
1026 packet +LENGTH_TS_HEADER +len_afh +1, | |
1027 LENGTH_PACKET -LENGTH_TS_HEADER -len_afh -1); | |
1028 pesbuf->size += LENGTH_PACKET -LENGTH_TS_HEADER -len_afh -1; | |
1029 } | |
1030 } else { | |
1031 /* ペイロードのみ */ | |
1032 /* TSヘッダを取り除いてPESバッファ書き込み */ | |
1033 if ( pesbuf->size != 0 ) { | |
1034 memcpy(pesbuf->buffer +pesbuf->size, | |
1035 packet +LENGTH_TS_HEADER, | |
1036 LENGTH_PACKET -LENGTH_TS_HEADER); | |
1037 pesbuf->size += LENGTH_PACKET -LENGTH_TS_HEADER; | |
1038 } | |
1039 } | |
1040 return 0; | |
1041 } | |
1042 #endif | |
1043 | |
1044 /* pesbufが空か判定 (ret. 0:not empty / 1: empty) */ | 976 /* pesbufが空か判定 (ret. 0:not empty / 1: empty) */ |
1045 static int pesbuf_empty(splitpesbuf_t *pesbuf){ | 977 static int pesbuf_empty(splitpesbuf_t *pesbuf){ |
1046 return pesbuf->size == 0; | 978 return pesbuf->size == 0; |
1047 } | 979 } |
1048 | 980 |
1091 } | 1023 } |
1092 | 1024 |
1093 /** | 1025 /** |
1094 * TSの解析とDemuxを行う | 1026 * TSの解析とDemuxを行う |
1095 */ | 1027 */ |
1096 //static int ts2pes(int64_t *ppts, int64_t *pdts, const uint8_t *packet, splitpesbuf_t *pesbuf, splitesbuf_t *esbuf, const int pid) | |
1097 static int DemuxTs(const uint8_t *packet, splitter *sp, const int pid, int *random_access) | 1028 static int DemuxTs(const uint8_t *packet, splitter *sp, const int pid, int *random_access) |
1098 { | 1029 { |
1099 /* | 1030 /* |
1100 * PES先頭までの長さは | 1031 * PES先頭までの長さは |
1101 * 4byte : continity counter | 1032 * 4byte : continity counter |
1128 return 0; /* 別にエラーではない */ | 1059 return 0; /* 別にエラーではない */ |
1129 } else if ( adaptation_field_control == 0x03 ) { | 1060 } else if ( adaptation_field_control == 0x03 ) { |
1130 /* アダプテーションフィールド+ペイロードの場合 */ | 1061 /* アダプテーションフィールド+ペイロードの場合 */ |
1131 if ( packet[LENGTH_TS_HEADER] != 0 ) { | 1062 if ( packet[LENGTH_TS_HEADER] != 0 ) { |
1132 random_access_indicator = (packet[5] & 0x40) >> 6; | 1063 random_access_indicator = (packet[5] & 0x40) >> 6; |
1133 sp->pesbuf[pid]->random_access_indicator = 1; | |
1134 sp->esbuf[pid]->random_access_indicator = 1; | |
1135 } | 1064 } |
1136 /* ペイロード開始位置 = TSヘッダ長 + アダプテーションフィールド長 + 1 */ | 1065 /* ペイロード開始位置 = TSヘッダ長 + アダプテーションフィールド長 + 1 */ |
1137 payload_offset += packet[LENGTH_TS_HEADER] + 1; | 1066 payload_offset += packet[LENGTH_TS_HEADER] + 1; |
1138 } else { | 1067 } else { |
1139 /* ペイロードのみ */ | 1068 /* ペイロードのみ */ |
1147 } | 1076 } |
1148 | 1077 |
1149 /* payload_unit_start_indicatorを処理(1) */ | 1078 /* payload_unit_start_indicatorを処理(1) */ |
1150 payload_unit_start_indicator = (packet[1] & 0x40) >> 6; | 1079 payload_unit_start_indicator = (packet[1] & 0x40) >> 6; |
1151 /* (sectionの場合は、ここでpointer_fieldの処理などを行い、payload_offsetに反映する) */ | 1080 /* (sectionの場合は、ここでpointer_fieldの処理などを行い、payload_offsetに反映する) */ |
1152 // if ( sp->pmt_pids[pid] == 2 ) { /* PID が録画対象の PMT であるか? */ | |
1153 // int sid = search_pmt_program(sp, pid); /* PID が録画対象の PMT であるか? */ | |
1154 if ( sp->pmt_pids[pid] == 2 ) { /* PID が録画対象の PMT であるか? */ | 1081 if ( sp->pmt_pids[pid] == 2 ) { /* PID が録画対象の PMT であるか? */ |
1155 if ( get_pmt_version(packet+payload_offset) != sp->program[sid].pmt_version ) { | 1082 if ( get_pmt_version(packet+payload_offset) != sp->program[sid].pmt_version ) { |
1156 /* pmt versionに差分あり */ | 1083 /* pmt versionに差分あり */ |
1157 fprintf(stderr, "pmt version diff found pmt_pid[%d]" | 1084 fprintf(stderr, "pmt version diff found pmt_pid[%d]" |
1158 " old_version[0x%02x]" | 1085 " old_version[0x%02x]" |
1170 /* 必要に応じ、蓄積済みPESの処理と、PES蓄積開始を行う */ | 1097 /* 必要に応じ、蓄積済みPESの処理と、PES蓄積開始を行う */ |
1171 if( payload_unit_start_indicator ){ | 1098 if( payload_unit_start_indicator ){ |
1172 /* PES開始 */ | 1099 /* PES開始 */ |
1173 if ( pes_started ) { | 1100 if ( pes_started ) { |
1174 /* バッファにデータがあればPES終端なので処理してクリア */ | 1101 /* バッファにデータがあればPES終端なので処理してクリア */ |
1175 pes2es(sp->pesbuf[pid], sp->esbuf[pid], pid); | 1102 pes2es(sp->pesbuf[pid], sp->esbuf[pid], pid, random_access_indicator); |
1176 pesbuf_clear(sp->pesbuf[pid]); | 1103 pesbuf_clear(sp->pesbuf[pid]); |
1177 } | 1104 } |
1178 else { | 1105 else { |
1179 /* random_access_indicator からPES の蓄積を開始すると | |
1180 * CS:動画がGOP先頭から蓄積されるが、 | |
1181 * 音声には random_access_indicator が表れないのでダメ | |
1182 */ | |
1183 pes_started = 1; | 1106 pes_started = 1; |
1184 } | 1107 } |
1185 } | 1108 } |
1186 | 1109 |
1187 /* PES蓄積処理 */ | 1110 /* PES蓄積処理 */ |
1194 } | 1117 } |
1195 | 1118 |
1196 /* PMT_PID から Program(Service ID)を確定させる */ | 1119 /* PMT_PID から Program(Service ID)を確定させる */ |
1197 static int search_pmt_program(splitter *sp, int pid) | 1120 static int search_pmt_program(splitter *sp, int pid) |
1198 { | 1121 { |
1122 /* この関数は大変遅いのでなるべく使用しない */ | |
1199 int i; | 1123 int i; |
1200 for ( i = 0; i < MAX_SERVICE_ID; i++ ) { | 1124 for ( i = 0; i < MAX_SERVICE_ID; i++ ) { |
1201 if ( sp->program[i].pmt_packet_id == pid ) { | 1125 if ( sp->program[i].pmt_packet_id == pid ) { |
1202 return i; | 1126 return i; |
1203 } | 1127 } |
1227 } | 1151 } |
1228 | 1152 |
1229 /* | 1153 /* |
1230 * PESを解析してESを出力する | 1154 * PESを解析してESを出力する |
1231 */ | 1155 */ |
1232 static int pes2es(splitpesbuf_t *pesbuf, splitesbuf_t *esbuf, const int pid) | 1156 static int pes2es(splitpesbuf_t *pesbuf, splitesbuf_t *esbuf, const int pid, int random_access_indicator) |
1233 { | 1157 { |
1234 int len_pesh = 0; | 1158 int len_pesh = 0; |
1235 int code = 0; | 1159 int code = 0; |
1236 int flags = 0; | 1160 int flags = 0; |
1237 int len_pes = 0; | 1161 int len_pes = 0; |
1245 int original_stuffing_length = 0; | 1169 int original_stuffing_length = 0; |
1246 int data_alignment_indicator = false; | 1170 int data_alignment_indicator = false; |
1247 int es_started; | 1171 int es_started; |
1248 int payload_offset = 0; | 1172 int payload_offset = 0; |
1249 int payload_length = 0; | 1173 int payload_length = 0; |
1174 int audio_lipsync_offset = 0; | |
1175 int i = 0; | |
1176 int64_t audio_pts = 0; | |
1177 int adts_freq = 0; | |
1178 int64_t adts_frame_time = 0; | |
1179 int audio_accumulation = 0; | |
1250 /* ありがとう */ | 1180 /* ありがとう */ |
1251 /* ありがとうとコメントを書くと、 | 1181 /* ありがとうとコメントを書くと、 |
1252 * 動作がよくなる | 1182 * 動作がよくなる |
1253 * バグが減る | 1183 * バグが減る |
1254 * バイナリサイズが小さくなる | 1184 * バイナリサイズが小さくなる |
1264 payload_offset = pesbuf_packet_start_code_prefix(pesbuf); | 1194 payload_offset = pesbuf_packet_start_code_prefix(pesbuf); |
1265 if ( payload_offset == -1 ) { | 1195 if ( payload_offset == -1 ) { |
1266 return -1; | 1196 return -1; |
1267 } | 1197 } |
1268 p += payload_offset; | 1198 p += payload_offset; |
1269 #if 0 | |
1270 while( p < p_end -LENGTH_PES_HEADER -2) { | |
1271 /* PES PREFIXが出現するまで読み捨てる */ | |
1272 if ( (p[0] == 0x00 && p[1] == 0x00 && p[2] == 0x01) ) { | |
1273 break; | |
1274 } else { | |
1275 offset++; | |
1276 p++; | |
1277 } | |
1278 } | |
1279 if ( p >= p_end -LENGTH_PES_HEADER -2) { | |
1280 return -1; | |
1281 } | |
1282 #endif | |
1283 /* http://dvd.sourceforge.net/dvdinfo/pes-hdr.html | 1199 /* http://dvd.sourceforge.net/dvdinfo/pes-hdr.html |
1284 * | 1200 * |
1285 * Stream ID : type : extension present? | 1201 * Stream ID : type : extension present? |
1286 * (1011 1101) 0xBD : Private stream 1 (non MPEG audio, subpictures) : YES | 1202 * (1011 1101) 0xBD : Private stream 1 (non MPEG audio, subpictures) : YES |
1287 * (1011 1110) 0xBE : Padding stream : NO | 1203 * (1011 1110) 0xBE : Padding stream : NO |
1341 /* おそらくここで区切るとピクチャ単位 */ | 1257 /* おそらくここで区切るとピクチャ単位 */ |
1342 //printf("data alignment indicator found pid[%d].\n", pid); | 1258 //printf("data alignment indicator found pid[%d].\n", pid); |
1343 } | 1259 } |
1344 flags = p[7] & 0xff; | 1260 flags = p[7] & 0xff; |
1345 /* PESヘッダデータ長(byte 8) */ | 1261 /* PESヘッダデータ長(byte 8) */ |
1346 /* | |
1347 * PESヘッダデータ長 = PESヘッダ拡張部の長さ + stuffing byteの長さ | |
1348 */ | |
1349 /* | |
1350 *len_pesh = flags(byte 7)のデータ合計(24) | |
1351 * +PES Extension flagのデータ合計(23) | |
1352 * +PES Extension flag2のデータ合計(127) | |
1353 * +stuffing byte(32) <- これもlen_peshの長さに混ぜていいの? | |
1354 * MAX=206(?) | |
1355 */ | |
1356 len_pesh = p[8] & 0xff; | 1262 len_pesh = p[8] & 0xff; |
1357 p += LENGTH_PES_HEADER; | 1263 p += LENGTH_PES_HEADER; |
1358 payload_offset += LENGTH_PES_HEADER +len_pesh; | 1264 payload_offset += LENGTH_PES_HEADER +len_pesh; |
1359 if ( p +payload_offset >= p_end ) { | 1265 if ( p +payload_offset >= p_end ) { |
1360 /* PESヘッダ長すぎます */ | 1266 /* PESヘッダ長すぎます */ |
1377 */ | 1283 */ |
1378 if ( flags & PTS_FLAG ) { | 1284 if ( flags & PTS_FLAG ) { |
1379 if ( p +LENGTH_PTS >= p_end ) { | 1285 if ( p +LENGTH_PTS >= p_end ) { |
1380 return -1; | 1286 return -1; |
1381 } | 1287 } |
1382 esbuf->pts = get_pts(p); | 1288 pesbuf->pts = get_pts(p); |
1383 p += LENGTH_PTS; | 1289 p += LENGTH_PTS; |
1384 len_pesh_supposed += LENGTH_PTS; | 1290 len_pesh_supposed += LENGTH_PTS; |
1385 } | 1291 } |
1386 if ( flags & DTS_FLAG ) { | 1292 if ( flags & DTS_FLAG ) { |
1387 if ( p +LENGTH_PTS >= p_end ) { | 1293 if ( p +LENGTH_PTS >= p_end ) { |
1388 return -1; | 1294 return -1; |
1389 } | 1295 } |
1390 esbuf->dts = get_pts(p); | 1296 pesbuf->dts = get_pts(p); |
1391 p += LENGTH_PTS; | 1297 p += LENGTH_PTS; |
1392 len_pesh_supposed += LENGTH_PTS; | 1298 len_pesh_supposed += LENGTH_PTS; |
1393 } | 1299 } |
1394 if ( flags & ESCR_FLAG ) { | 1300 if ( flags & ESCR_FLAG ) { |
1395 p += 6; | 1301 p += 6; |
1481 | 1387 |
1482 p += pes_extension_flags2; | 1388 p += pes_extension_flags2; |
1483 len_pesh_supposed += pes_extension_flags2; | 1389 len_pesh_supposed += pes_extension_flags2; |
1484 } | 1390 } |
1485 } | 1391 } |
1486 #if 0 | 1392 payload_length = pesbuf->size -payload_offset; |
1487 /* | |
1488 * 画像であれば、PTS/DTSが立っていた場合に出力して、 | |
1489 * それ以外であれば、PTSが立っていた場合にのみ出力にすると、 | |
1490 * GOP的なまとまりで出力できる? | |
1491 */ | |
1492 /* esbuf->size が 0 であるのはは初期化後、初めてここに到達した場合 */ | |
1493 if ((have_data_alignment_indicator) && (esbuf->size != 0)) { | |
1494 /* ここのタイミングでパックヘッダつけてあげればPSになるはず */ | |
1495 /* ピクチャ先頭パケット */ | |
1496 write_es(esbuf, pid); | |
1497 memcpy(esbuf->buffer, | |
1498 pesbuf->buffer +offset +LENGTH_PES_HEADER +len_pesh, | |
1499 pesbuf->size -offset -LENGTH_PES_HEADER -len_pesh); | |
1500 esbuf->size = pesbuf->size -offset -LENGTH_PES_HEADER -len_pesh; | |
1501 } else if (have_data_alignment_indicator && (esbuf->size == 0)) { | |
1502 /* プロセス起動してから最初のピクチャ先頭データ */ | |
1503 memcpy(esbuf->buffer, | |
1504 pesbuf->buffer +offset +LENGTH_PES_HEADER +len_pesh, | |
1505 pesbuf->size -offset -LENGTH_PES_HEADER -len_pesh); | |
1506 esbuf->size = pesbuf->size -offset -LENGTH_PES_HEADER -len_pesh; | |
1507 } else if(esbuf->size != 0) { | |
1508 /* それ以外のPESデータ */ | |
1509 memcpy(esbuf->buffer + esbuf->size, | |
1510 pesbuf->buffer +offset +LENGTH_PES_HEADER +len_pesh, | |
1511 pesbuf->size -offset -LENGTH_PES_HEADER -len_pesh); | |
1512 esbuf->size += pesbuf->size -offset -LENGTH_PES_HEADER -len_pesh; | |
1513 } else { | |
1514 /* 読み捨て */ | |
1515 /* プロセス起動直後のデータは捨てる(GOP境界をまたいだパケットから書き始めない為) */ } | |
1516 printf("len_pesh_supposed[%d], len_pesh[%d].\n", len_pesh_supposed, len_pesh); | |
1517 #endif | |
1518 if ( data_alignment_indicator ) { | 1393 if ( data_alignment_indicator ) { |
1519 if ( es_started ) { /* ES にデータが蓄積されている */ | 1394 if ( es_started ) { /* ES にデータが蓄積されている */ |
1520 if ( is_video_stream(pid, esbuf) ) { /* VIDEO である場合 */ | 1395 if ( is_video_stream(pid, esbuf) && !(esbuf->started) ) { /* VIDEO である場合 */ |
1521 /* | 1396 /* random_access ビットが立っている場合は、GOP先頭である */ |
1522 * ESにはピクチャ単位でデータが蓄積されている | 1397 if ( random_access_indicator ) { /* TS の random_access ビットが立ったものがきているか? */ |
1523 * ESにGOPの開始コードが含まれているか調べて、 | 1398 /* 該当ストリームを蓄積開始する */ |
1524 * 含まれていたら、蓄積開始のフラグを立てるのがいいかも… | |
1525 */ | |
1526 if ( esbuf->random_access_indicator ) { /* TS の random_access ビットが立ったものがきているか? */ | |
1527 /* 該当ストリームを蓄積する */ | |
1528 esbuf->started = 1; | 1399 esbuf->started = 1; |
1529 esbuf->Program->video_start = 1; | 1400 esbuf->Program->video_start = 1; |
1530 esbuf->Program->video_pts = esbuf->pts; | 1401 esbuf->Program->video_pts = esbuf->pts; |
1402 printf("video stream. pid[%d] v_pts[%llu].\n", pid, esbuf->pts); | |
1531 } else { | 1403 } else { |
1532 /* TS の random_access ビットが立ったものがきていない */ | 1404 /* TS の random_access ビットが立ったものがきていない */ |
1533 /* 蓄積しない */ | 1405 /* 蓄積開始しない */ |
1534 esbuf_clear(esbuf); | 1406 esbuf_clear(esbuf); |
1407 esbuf->pts = pesbuf->pts; | |
1408 esbuf->dts = pesbuf->dts; | |
1535 } | 1409 } |
1536 } | 1410 } |
1537 /* AAC の実験コードここから */ | 1411 /* AAC の実験コードここから */ |
1538 /* | 1412 /* |
1539 * オーディオを出力し始める条件(1. 2. を満たすこと) | 1413 * オーディオを出力し始める条件(1. 2. を満たすこと) |
1541 * 2. 動画のGOPの1番目のIピクチャのPTSとオーディオのPTSを比較して以下のどちらかを満たすこと | 1415 * 2. 動画のGOPの1番目のIピクチャのPTSとオーディオのPTSを比較して以下のどちらかを満たすこと |
1542 * 2.1. 差分が11msec以内 | 1416 * 2.1. 差分が11msec以内 |
1543 * 2.2. 過ぎている(過ぎている場合はオーディオESの蓄積の継続と次のGOP狙いにする?) | 1417 * 2.2. 過ぎている(過ぎている場合はオーディオESの蓄積の継続と次のGOP狙いにする?) |
1544 * #GOP先頭にこだわり過ぎると録画を逃すという線もあるので、適当に手を打つのも手 | 1418 * #GOP先頭にこだわり過ぎると録画を逃すという線もあるので、適当に手を打つのも手 |
1545 */ | 1419 */ |
1546 else { | 1420 else if ( is_audio_stream(pid, esbuf) && !(esbuf->started) ) { |
1547 esbuf->started = 1; | 1421 if ( !(esbuf->Program->video_start) ) { |
1548 } | 1422 /* |
1549 #if 0 | 1423 * VIDEO が始まってない場合、 |
1550 if ( is_audio_stream(pid, esbuf) && esbuf->Program->video_start ) { | 1424 * ESバッファの余裕がある限り蓄積続けちゃえばいいんでない? |
1551 int audio_lipsync_offset = 0; | 1425 */ |
1552 int i; | 1426 audio_accumulation = 1; /* ESバッファにオーディオを追記する */ |
1553 int64_t audio_pts = esbuf->pts; | 1427 if ( esbuf->size > sizeof esbuf->buffer -payload_length ){ |
1554 int adts_freq = AnalyzeAdifHeader(esbuf); | 1428 /* 溢れそうになったらクリア */ |
1555 int64_t adts_frame_time = ((1000/adts_freq) *27e6); /* PTSは27MHz */ | 1429 esbuf_clear(esbuf); |
1556 /* オーディオ且つ、Programのビデオ蓄積が開始されていればオーディオの蓄積を行う */ | 1430 esbuf->pts = pesbuf->pts; |
1557 while ( (esbuf->Program->video_pts > audio_pts +adts_frame_time/2) ) { | 1431 esbuf->dts = pesbuf->dts; |
1558 /* オーディオデータを捨てると audio_pts は1フレーム分大きくなる */ | 1432 audio_accumulation = 0; |
1559 i = esbuf_adts_start_code_prefix(esbuf, audio_lipsync_offset); /* 次のAACのデータを取得 */ | |
1560 if ( i != -1 ) { /* AACデータの終端か? */ | |
1561 audio_lipsync_offset += i; | |
1562 } else { | |
1563 break; | |
1564 } | 1433 } |
1565 audio_pts += adts_frame_time; /* AACの1フレーム分、時間を進める */ | |
1566 } | 1434 } |
1567 if ( esbuf->size != audio_lipsync_offset ) { /* 一致していない場合はコピー */ | 1435 else if ( esbuf->Program->video_start ) { /* video 蓄積が開始されているので音声側の頭を揃える */ |
1568 memmove(esbuf->buffer +audio_lipsync_offset, | 1436 printf("audio stream. pid[%d] a_pts[%llu] v_pts[%llu].\n", pid, esbuf->pts, esbuf->Program->video_pts); |
1569 esbuf->buffer, | 1437 audio_lipsync_offset = 0; |
1570 esbuf->size -audio_lipsync_offset); | 1438 audio_pts = esbuf->pts; |
1571 esbuf->size -= audio_lipsync_offset; | 1439 adts_freq = AnalyzeAdifHeader(esbuf); |
1572 esbuf->started = 1; | 1440 adts_frame_time = (int64_t)((float)1000*90000/adts_freq); /* PTSは90KHz */ |
1441 while ( (esbuf->Program->video_pts > audio_pts +adts_frame_time/2) ) { | |
1442 /* オーディオデータを捨てると audio_pts は1フレーム分大きくなる */ | |
1443 i = esbuf_adts_start_code_prefix(esbuf, audio_lipsync_offset); /* 次のAACのデータを取得 */ | |
1444 if ( i != -1 ) { /* AACデータの終端か? */ | |
1445 audio_lipsync_offset += i; | |
1446 } else { | |
1447 break; | |
1448 } | |
1449 printf("audio stream drop. pid[%d] pts[%llu].\n", pid, audio_pts); | |
1450 audio_pts += adts_frame_time; /* AACの1フレーム分、時間を進める */ | |
1451 } | |
1452 if ( (esbuf->Program->video_pts <= audio_pts +adts_frame_time/2) ) { | |
1453 printf("lipsync start. v_pts[%llu] a_pts[%llu].\n", esbuf->Program->video_pts, audio_pts); | |
1454 memmove(esbuf->buffer +audio_lipsync_offset, | |
1455 esbuf->buffer, | |
1456 esbuf->size -audio_lipsync_offset); | |
1457 esbuf->size -= audio_lipsync_offset; | |
1458 esbuf->started = 1; | |
1459 } | |
1460 } | |
1461 else { | |
1462 ; /* 該当するものは無いはず */ | |
1573 } | 1463 } |
1574 } | 1464 } |
1575 #endif | |
1576 /* AAC の実験コードここまで */ | 1465 /* AAC の実験コードここまで */ |
1577 /* バッファをファイルに出力してクリア */ | 1466 /* バッファをファイルに出力してクリア */ |
1578 if ( esbuf->started ) { | 1467 if ( esbuf->started ) { |
1579 esbuf_write(esbuf, pid); | 1468 esbuf_write(esbuf, pid); |
1580 esbuf_clear(esbuf); | 1469 esbuf_clear(esbuf); |
1470 esbuf->pts = pesbuf->pts; | |
1471 esbuf->dts = pesbuf->dts; | |
1581 } | 1472 } |
1582 } else { | 1473 } else { |
1583 /* ES蓄積を新たに開始 */ | 1474 /* ES蓄積を新たに開始 */ |
1584 es_started = 1; | 1475 es_started = 1; |
1585 } | 1476 } |
1586 } | 1477 } |
1587 | 1478 |
1588 payload_length = pesbuf->size -payload_offset; | |
1589 /* ES蓄積処理 */ | 1479 /* ES蓄積処理 */ |
1590 if ( es_started ) { | 1480 if ( es_started ) { |
1481 if ( ! audio_accumulation ) { /* オーディオのESバッファへの蓄積をしていない */ | |
1482 esbuf->pts = pesbuf->pts; | |
1483 esbuf->dts = pesbuf->dts; | |
1484 } | |
1591 /* ES蓄積開始済み(これからES蓄積開始を含む)なら、payloadをESとして追加 */ | 1485 /* ES蓄積開始済み(これからES蓄積開始を含む)なら、payloadをESとして追加 */ |
1592 esbuf_add(esbuf, pesbuf->buffer +payload_offset, payload_length); | 1486 esbuf_add(esbuf, pesbuf->buffer +payload_offset, payload_length); |
1593 } | 1487 } |
1594 /* お疲れさまでした */ | 1488 /* お疲れさまでした */ |
1595 return 0; | 1489 return 0; |
1647 remain -= write(fd, esbuf->buffer+(esbuf->size-remain), remain); | 1541 remain -= write(fd, esbuf->buffer+(esbuf->size-remain), remain); |
1648 } | 1542 } |
1649 close(fd); | 1543 close(fd); |
1650 return 0; | 1544 return 0; |
1651 } | 1545 } |
1652 | |
1653 | 1546 |
1654 /* | 1547 /* |
1655 * packet dump | 1548 * packet dump |
1656 */ | 1549 */ |
1657 void dump_packet( const uint8_t *packet ) | 1550 void dump_packet( const uint8_t *packet ) |
1775 } | 1668 } |
1776 } | 1669 } |
1777 } | 1670 } |
1778 | 1671 |
1779 /* | 1672 /* |
1780 * この関数では、現在の仕様では、先頭位置の「次の」ADTS start codeまでの長さを返却します | 1673 * この関数では、現在の仕様では、先頭位置の「次の」ADTS start codeまでの長さを返却する |
1781 * ret == 0 : 仕様上あり得ない | 1674 * ret == 0 : 仕様上あり得ない |
1782 * ret > 0 : 見つかった場合 | 1675 * ret > 0 : 見つかった場合 |
1783 * ret == -1 : 見つからなかった場合 | 1676 * ret == -1 : 見つからなかった場合 |
1784 */ | 1677 */ |
1785 static int esbuf_adts_start_code_prefix(splitesbuf_t *esbuf, int offset) | 1678 static int esbuf_adts_start_code_prefix(splitesbuf_t *esbuf, int offset) |
1793 | 1686 |
1794 /* 小さすぎる */ | 1687 /* 小さすぎる */ |
1795 if(esbuf->size -offset < sizeof adts_start_code_prefix){ | 1688 if(esbuf->size -offset < sizeof adts_start_code_prefix){ |
1796 return -1; | 1689 return -1; |
1797 } | 1690 } |
1798 for(i = 1; i < esbuf->size -offset - sizeof adts_start_code_prefix; i++) { | 1691 for(; i < esbuf->size - sizeof adts_start_code_prefix; i++) { |
1799 if(!memcmp(esbuf->buffer +offset + i ,adts_start_code_prefix, sizeof adts_start_code_prefix)){ | 1692 if(!memcmp(esbuf->buffer + i ,adts_start_code_prefix, sizeof adts_start_code_prefix)){ |
1800 #if 0 | 1693 #if 0 |
1801 printf("adts start code found.i[%d]. 0[%02x] 1[%02x] 2[%02x] 3[%02x] 4[%02x] 5[%02x] 6[%02x]\n", | 1694 printf("adts start code found.i[%d]. 0[%02x] 1[%02x] 2[%02x] 3[%02x] 4[%02x] 5[%02x] 6[%02x]\n", |
1802 i, *(esbuf->buffer+i+0), *(esbuf->buffer+i+1), *(esbuf->buffer+i+2), *(esbuf->buffer+i+3), *(esbuf->buffer+i+4), *(esbuf->buffer+i+5), *(esbuf->buffer+i+6) ); | 1695 i, *(esbuf->buffer+i+0), *(esbuf->buffer+i+1), *(esbuf->buffer+i+2), *(esbuf->buffer+i+3), *(esbuf->buffer+i+4), *(esbuf->buffer+i+5), *(esbuf->buffer+i+6) ); |
1803 #endif | 1696 #endif |
1804 return i; | 1697 return (i-offset); |
1805 } | 1698 } |
1806 } | 1699 } |
1807 return -1; | 1700 return -1; |
1808 } | 1701 } |
1809 | 1702 |