22 #include "libmythbase/mythconfig.h"
29 #include "libavutil/cpu.h"
30 #include "libmythmpeg2/attributes.h"
31 #include "libmythmpeg2/mpeg2.h"
32 #include "libmythmpeg2/mpeg2_internal.h"
41 #include <netinet/in.h>
48 static void *
my_malloc(
unsigned size, [[maybe_unused]] mpeg2_alloc_t reason)
52 char *buf = (
char *) malloc (size + 63 +
sizeof (
void **));
55 memset(buf, 0, size + 63 +
sizeof (
void **));
56 char *align_buf = buf + 63 +
sizeof (
void **);
57 align_buf -= (
long)align_buf & 63;
58 *(((
void **)align_buf) - 1) = buf;
67 int level,
const char* fmt, va_list vl)
69 static QString s_fullLine(
"");
71 if (level > AV_LOG_INFO)
74 s_fullLine += QString::vasprintf(fmt, vl);
75 if (s_fullLine.endsWith(
"\n"))
78 LOG(VB_GENERAL, LOG_INFO, s_fullLine);
79 s_fullLine = QString(
"");
91 return QString(
"%1%2:%3:%4.%5")
92 .arg(is_neg ?
"-" :
"")
93 .arg((
uint)(
pts / 90000.) / 3600, 2, 10, QChar(
'0'))
94 .arg(((
uint)(
pts / 90000.) % 3600) / 60, 2, 10, QChar(
'0'))
95 .arg(((
uint)(
pts / 90000.) % 3600) % 60, 2, 10, QChar(
'0'))
96 .arg(((((
uint)(
pts / 90.) % 3600000) % 60000) % 1000), 3, 10, QChar(
'0'));
100 m_mpeg2_seq(), m_mpeg2_gop(), m_mpeg2_pic()
102 m_pkt = av_packet_alloc();
103 av_new_packet(
m_pkt, size);
108 av_packet_free(&
m_pkt);
113 if (
m_pkt->size < size)
115 int oldSize =
m_pkt->size;
116 if ((av_grow_packet(
m_pkt, size -
m_pkt->size) < 0) ||
m_pkt->size < size)
118 LOG(VB_GENERAL, LOG_CRIT, QString(
"MPEG2frame::ensure_size(): "
119 "Failed to grow packet size "
120 "from %1 to %2, result was %3")
121 .arg(oldSize).arg(size)
130 av_packet_unref(
m_pkt);
131 av_packet_ref(
m_pkt, newpkt);
141 idx.newPTS = initPTS;
146 for (
const int key : qAsConst(
m_keyList))
152 QList<poq_idx_t>::iterator it;
153 int64_t value =
m_offset[idx].first().newPTS;
161 while (
m_offset[idx].count() > 1 && !done)
164 if (((
static_cast<int>((*it).type) == 0) &&
165 (pkt->pts >= (*it).pos_pts) ) ||
167 ((pkt->pos >= (*it).pos_pts) || (pkt->duration > (*it).framenum))))
170 value =
m_offset[idx].first().newPTS;
187 for (
const int key : qAsConst(
m_keyList))
197 idx.framenum = pkt->duration;
200 LOG(VB_FRAME, LOG_INFO, QString(
"Offset %1 -> %2 (%3) at %4")
203 PtsTime(delta), QString::number(pkt->pos)));
204 for (
const int key : qAsConst(
m_keyList))
209 m_orig[key].push_back(idx);
216 QList<poq_idx_t> *dltaList = &
m_orig[idx];
217 while (!dltaList->isEmpty() &&
218 (pkt->pos >= dltaList->first().pos_pts ||
219 pkt->duration > dltaList->first().framenum))
221 if (dltaList->first().newPTS >= 0)
222 ptsinc((uint64_t *)&origPTS, 300 * dltaList->first().newPTS);
224 ptsdec((uint64_t *)&origPTS, -300 * dltaList->first().newPTS);
225 delta += dltaList->first().newPTS;
226 dltaList->pop_front();
227 LOG(VB_PROCESS, LOG_INFO,
228 QString(
"Moving PTS offset of stream %1 by %2")
229 .arg(idx).arg(
PtsTime(delta)));
236 const char *fmt,
bool norp,
bool fixPTS,
int maxf,
237 bool showprog,
int otype,
void (*update_func)(
float),
239 : m_noRepeat(norp), m_fixPts(fixPTS), m_maxFrames(maxf),
240 m_infile(inf), m_format(fmt)
245 if (deleteMap && !deleteMap->isEmpty())
248 frm_dir_map_t::iterator it = deleteMap->begin();
249 for (; it != deleteMap->end(); ++it)
251 uint64_t
mark = it.key();
303 const QFileInfo finfo(inf);
331 while (!af->isEmpty())
345 {
return (ptr[0] == 0x00) && (ptr[1] == 0x00) && (ptr[2] == 0x01); };
347 static void SETBITS(
unsigned char *ptr,
long value,
int num)
349 static int s_sbPos = 0;
350 static unsigned char *s_sbPtr =
nullptr;
358 if (s_sbPtr ==
nullptr)
361 int offset = s_sbPos >> 3;
362 int offset_r = s_sbPos & 0x07;
363 int offset_b = 32 - offset_r;
364 uint32_t mask = ~(((1 << num) - 1) << (offset_b - num));
365 uint32_t sb_long = ntohl(*((uint32_t *) (s_sbPtr + offset)));
366 value = value << (offset_b - num);
367 sb_long = (sb_long & mask) + value;
368 *((uint32_t *)(s_sbPtr + offset)) = htonl(sb_long);
378 *pts1 = (*pts1 + pts2) %
MAX_PTS;
383 int64_t diff = pts1 - pts2;
402 return (pts1 - pts2);
406 return (pts1 +
MAX_PTS - pts2);
410 return (pts1 - (pts2 +
MAX_PTS));
419 int64_t
tmp = pts1 + pts2;
421 return (pts1 + pts2) %
MAX_PTS;
431 if ((uint64_t)(pts1 - pts2) >
MAX_PTS/2ULL)
436 else if (pts1 == pts2)
440 if ((uint64_t)(pts2 - pts1) >
MAX_PTS/2ULL)
450 for (
int i = 0; i < size; i++)
470 return (rx->WaitBuffers());
491 pthread_mutex_lock( &
m_mutex );
506 pthread_cond_signal(&
m_cond);
509 pthread_mutex_unlock(&
m_mutex);
515 static int errorcount = 0;
518 LOG(VB_GENERAL, LOG_ERR,
519 QString(
"thread finished with %1 write errors")
522 pthread_exit(&errorcount);
557 mx.
priv = (
void *)
this;
559 int fd_out = open(
m_outfile.toLocal8Bit().constData(),
564 pthread_cond_signal(&
m_cond);
566 pthread_mutex_unlock(&
m_mutex);
589 #define INDEX_BUF (sizeof(index_unit) * 200)
596 if (
m_vFrame.first()->m_mpeg2_seq.height >= 720)
598 LOG(VB_GENERAL, LOG_NOTICE,
"MPEG2fixup::InitReplex(): High Definition input, increasing replex buffers");
605 LOG(VB_GENERAL, LOG_WARNING,
"MPEG2fixup::InitReplex(): Using '--ostream=dvd' with HD video is an invalid combination");
610 uint32_t memsize =
m_vFrame.first()->m_mpeg2_seq.width *
611 m_vFrame.first()->m_mpeg2_seq.height * 10;
623 uint index = it.key();
627 if (avctx ==
nullptr)
630 AVDictionaryEntry *metatag =
631 av_dict_get(
m_inputFC->streams[index]->metadata,
632 "language",
nullptr, 0);
633 char *lang = metatag ? metatag->value : (
char *)
"";
642 case AV_CODEC_ID_MP2:
643 case AV_CODEC_ID_MP3:
647 case AV_CODEC_ID_AC3:
657 26999999ULL) /
m_vFrame.first()->m_mpeg2_seq.frame_period;
664 QString msg = QString(
"Id:%1 %2 V:%3").arg(f->
m_pkt->stream_index)
672 msg += QString(
" %2")
675 LOG(VB_RPLXQUEUE, LOG_INFO, msg);
683 int id = f->
m_pkt->stream_index;
694 iu.gop =
static_cast<uint8_t
>(f->
m_isGop);
698 iu.dts = f->
m_pkt->dts * 300;
706 iu.framesize = f->
m_pkt->size;
711 LOG(VB_GENERAL, LOG_ERR,
"Ringbuffer pointers empty. No stream found");
716 iu.length = f->
m_pkt->size;
717 iu.pts = f->
m_pkt->pts * 300;
741 unsigned int inc_size = 10 * (
unsigned int)f->
m_pkt->size;
742 LOG(VB_GENERAL, LOG_NOTICE,
743 QString(
"Increasing ringbuffer size by %1 to avoid deadlock")
753 LOG(VB_GENERAL, LOG_ERR,
754 "Deadlock detected. One buffer is full when "
755 "the other is empty! Aborting");
768 LOG(VB_GENERAL, LOG_ERR,
769 QString(
"Ring buffer overflow %1").arg(rb->
size));
776 LOG(VB_GENERAL, LOG_ERR,
777 QString(
"Ring buffer overflow %1").arg(rbi->
size));
787 QByteArray ifarray = inputfile.toLocal8Bit();
788 const char *ifname = ifarray.constData();
790 const AVInputFormat *fmt =
nullptr;
793 fmt = av_find_input_format(
type);
796 LOG(VB_GENERAL, LOG_INFO, QString(
"Opening %1").arg(inputfile));
804 int ret = avformat_open_input(&
m_inputFC, ifname, fmt,
nullptr);
807 LOG(VB_GENERAL, LOG_ERR,
808 QString(
"Couldn't open input file, error #%1").arg(ret));
815 fmt = av_find_input_format(
"mpegts-ffmpeg");
818 LOG(VB_PLAYBACK, LOG_INFO,
"Using FFmpeg MPEG-TS demuxer (forced)");
820 ret = avformat_open_input(&
m_inputFC, ifname, fmt,
nullptr);
823 LOG(VB_GENERAL, LOG_ERR,
824 QString(
"Couldn't open input file, error #%1").arg(ret));
836 ret = avformat_find_stream_info(
m_inputFC,
nullptr);
839 LOG(VB_GENERAL, LOG_ERR,
840 QString(
"Couldn't get stream info, error #%1").arg(ret));
850 for (
unsigned int i = 0; i <
m_inputFC->nb_streams; i++)
852 switch (
m_inputFC->streams[i]->codecpar->codec_type)
854 case AVMEDIA_TYPE_VIDEO:
859 case AVMEDIA_TYPE_AUDIO:
861 m_inputFC->streams[i]->codecpar->ch_layout.nb_channels < 2 &&
862 m_inputFC->streams[i]->codecpar->sample_rate < 100000)
864 LOG(VB_GENERAL, LOG_ERR,
865 QString(
"Skipping audio stream: %1").arg(i));
868 if (
m_inputFC->streams[i]->codecpar->codec_id == AV_CODEC_ID_AC3 ||
869 m_inputFC->streams[i]->codecpar->codec_id == AV_CODEC_ID_MP3 ||
870 m_inputFC->streams[i]->codecpar->codec_id == AV_CODEC_ID_MP2)
877 LOG(VB_GENERAL, LOG_ERR,
878 QString(
"Skipping unsupported audio stream: %1")
879 .arg(
m_inputFC->streams[i]->codecpar->codec_id));
883 LOG(VB_GENERAL, LOG_ERR,
884 QString(
"Skipping unsupported codec %1 on stream %2")
885 .arg(
m_inputFC->streams[i]->codecpar->codec_type).arg(i));
905 int oldPktSize = frame1->
m_pkt->size;
907 memmove(frame1->
m_pkt->data + head_size, frame1->
m_pkt->data, oldPktSize);
908 memcpy(frame1->
m_pkt->data, frame2->
m_pkt->data, head_size);
913 static int count = 0;
914 QString
filename = QString(
"hdr%1.yuv").arg(count++);
932 auto *info = (mpeg2_info_t *)mpeg2_info(dec);
936 while (state != STATE_PICTURE)
938 state = mpeg2_parse(dec);
946 case STATE_SEQUENCE_MODIFIED:
947 case STATE_SEQUENCE_REPEATED:
949 sizeof(mpeg2_sequence_t));
954 memcpy(&vf->
m_mpeg2_gop, info->gop,
sizeof(mpeg2_gop_t));
962 sizeof(mpeg2_picture_t));
967 LOG(VB_GENERAL, LOG_WARNING,
968 "Warning: partial frame found!");
972 else if (state == STATE_BUFFER)
975 LOG(VB_GENERAL, LOG_ERR,
976 QString(
"Failed to decode frame. Position was: %1")
980 last_pos = (vf->
m_pkt->size - mpeg2_getpos(dec)) - 4;
985 while (state != STATE_BUFFER)
986 state = mpeg2_parse(dec);
987 if (info->display_picture)
994 std::array<uint8_t,8>
tmp {0x00, 0x00, 0x01, 0xb2, 0xff, 0xff, 0xff, 0xff};
995 mpeg2_buffer(dec,
tmp.data(),
tmp.data() + 8);
1002 QString msg = QString(
"");
1004 msg += QString(
"unused:%1 ") .arg(vf->
m_pkt->size - mpeg2_getpos(dec));
1008 msg += QString(
"%1x%2 P:%3 ").arg(info->sequence->width)
1009 .arg(info->sequence->height).arg(info->sequence->frame_period);
1013 QString gop = QString(
"%1:%2:%3:%4 ")
1014 .arg(info->gop->hours, 2, 10, QChar(
'0')).arg(info->gop->minutes, 2, 10, QChar(
'0'))
1015 .arg(info->gop->seconds, 2, 10, QChar(
'0')).arg(info->gop->pictures, 3, 10, QChar(
'0'));
1018 if (info->current_picture)
1020 int ct = info->current_picture->flags & PIC_MASK_CODING_TYPE;
1021 char coding_type = (ct == PIC_FLAG_CODING_TYPE_I) ?
'I' :
1022 ((ct == PIC_FLAG_CODING_TYPE_P) ?
'P' :
1023 ((ct == PIC_FLAG_CODING_TYPE_B) ?
'B' :
1024 ((ct == PIC_FLAG_CODING_TYPE_D) ?
'D' :
'X')));
1025 char top_bottom = (info->current_picture->flags &
1026 PIC_FLAG_TOP_FIELD_FIRST) ?
'T' :
'B';
1027 char progressive = (info->current_picture->flags &
1028 PIC_FLAG_PROGRESSIVE_FRAME) ?
'P' :
'_';
1029 msg += QString(
"#%1 fl:%2%3%4%5%6 ")
1030 .arg(info->current_picture->temporal_reference)
1031 .arg(info->current_picture->nb_fields)
1035 .arg(info->current_picture->flags >> 4, 0, 16);
1037 msg += QString(
"pos: %1").arg(vf->
m_pkt->pos);
1038 LOG(VB_DECODE, LOG_INFO, msg);
1047 if (tmpFrame ==
nullptr)
1051 for (
const auto & vf : qAsConst(
m_vFrame))
1053 if (vf->m_isSequence)
1067 if (tmpFrame ==
nullptr)
1073 mpeg2dec_t *tmp_decoder = mpeg2_init();
1074 auto *info = (mpeg2_info_t *)mpeg2_info(tmp_decoder);
1076 while (!info->display_picture)
1087 mpeg2_close(tmp_decoder);
1092 int fh = open(
filename.toLocal8Bit().constData(),
1093 O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
1096 LOG(VB_GENERAL, LOG_ERR,
1097 QString(
"Couldn't open file %1: ").arg(
filename) +
ENO);
1101 ssize_t ret =
write(fh, info->display_fbuf->buf[0],
1102 static_cast<size_t>(info->sequence->width) *
1103 static_cast<size_t>(info->sequence->height));
1106 LOG(VB_GENERAL, LOG_ERR, QString(
"write failed %1: ").arg(
filename) +
1110 ret =
write(fh, info->display_fbuf->buf[1],
1111 static_cast<size_t>(info->sequence->chroma_width) *
1112 static_cast<size_t>(info->sequence->chroma_height));
1115 LOG(VB_GENERAL, LOG_ERR, QString(
"write failed %1: ").arg(
filename) +
1119 ret =
write(fh, info->display_fbuf->buf[2],
1120 static_cast<size_t>(info->sequence->chroma_width) *
1121 static_cast<size_t>(info->sequence->chroma_height));
1124 LOG(VB_GENERAL, LOG_ERR, QString(
"write failed %1: ").arg(
filename) +
1134 int fh = open(
filename.toLocal8Bit().constData(),
1135 O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
1138 LOG(VB_GENERAL, LOG_ERR,
1139 QString(
"Couldn't open file %1: ").arg(
filename) +
ENO);
1143 int ret =
write(fh, data, size);
1145 LOG(VB_GENERAL, LOG_ERR, QString(
"write failed %1").arg(
filename) +
1152 alignas(16) std::array<uint16_t,64> intra_matrix {};
1153 int64_t savedPts = pkt->pts;
1156 if (!info->display_fbuf)
1159 int outbuf_size = info->sequence->width * info->sequence->height * 2;
1161 if (!fname.isEmpty())
1163 QString tmpstr = fname +
".yuv";
1180 if (pkt->size < outbuf_size)
1181 av_grow_packet(pkt, (outbuf_size - pkt->size));
1183 m_picture->data[0] = info->display_fbuf->buf[0];
1184 m_picture->data[1] = info->display_fbuf->buf[1];
1185 m_picture->data[2] = info->display_fbuf->buf[2];
1187 m_picture->linesize[0] = info->sequence->width;
1188 m_picture->linesize[1] = info->sequence->chroma_width;
1189 m_picture->linesize[2] = info->sequence->chroma_width;
1191 m_picture->opaque = info->display_fbuf->id;
1194 static constexpr std::array<uint8_t, 64> k_zigzag_scan = {
1195 0, 1, 8, 16, 9, 2, 3, 10,
1196 17, 24, 32, 25, 18, 11, 4, 5,
1197 12, 19, 26, 33, 40, 48, 41, 34,
1198 27, 20, 13, 6, 7, 14, 21, 28,
1199 35, 42, 49, 56, 57, 50, 43, 36,
1200 29, 22, 15, 23, 30, 37, 44, 51,
1201 58, 59, 52, 45, 38, 31, 39, 46,
1202 53, 60, 61, 54, 47, 55, 62, 63
1205 static std::array<uint16_t, 64> k_invZigzagDirect16 = {};
1206 for (
int i = 0; i < 64; i++)
1208 k_invZigzagDirect16[k_zigzag_scan[i]] = i;
1211 static constexpr std::array<uint16_t, 64> k_invZigzagDirect16 = {
1212 0, 1, 5, 6, 14, 15, 27, 28,
1213 2, 4, 7, 13, 16, 26, 29, 42,
1214 3, 8, 12, 17, 25, 30, 41, 43,
1215 9, 11, 18, 24, 31, 40, 44, 53,
1216 10, 19, 23, 32, 39, 45, 52, 54,
1217 20, 22, 33, 38, 46, 51, 55, 60,
1218 21, 34, 37, 47, 50, 56, 59, 61,
1219 35, 36, 48, 49, 57, 58, 62, 63,
1223 for (
int i = 0; i < 64; i++)
1225 intra_matrix[k_invZigzagDirect16[i]] =
m_imgDecoder->quantizer_matrix[0][i];
1228 if (info->display_picture->nb_fields % 2)
1230 m_picture->top_field_first = ((info->display_picture->flags &
1231 PIC_FLAG_TOP_FIELD_FIRST) != 0) ? 0 : 1;
1235 m_picture->top_field_first = ((info->display_picture->flags &
1236 PIC_FLAG_TOP_FIELD_FIRST) != 0) ? 1 : 0;
1239 m_picture->interlaced_frame = ((info->display_picture->flags &
1240 PIC_FLAG_PROGRESSIVE_FRAME) != 0) ? 0 : 1;
1242 const AVCodec *out_codec = avcodec_find_encoder(AV_CODEC_ID_MPEG2VIDEO);
1245 LOG(VB_GENERAL, LOG_ERR,
"Couldn't find MPEG2 encoder");
1249 AVCodecContext *c = avcodec_alloc_context3(
nullptr);
1256 c->flags |= AV_CODEC_FLAG_INTERLACED_DCT;
1258 c->bit_rate = info->sequence->byte_rate << 3;
1259 c->bit_rate_tolerance = c->bit_rate >> 2;
1260 c->width = info->sequence->width;
1261 c->height = info->sequence->height;
1262 av_reduce(&c->time_base.num, &c->time_base.den,
1263 info->sequence->frame_period, 27000000LL, 100000);
1264 c->pix_fmt = AV_PIX_FMT_YUV420P;
1265 c->max_b_frames = 0;
1266 c->has_b_frames = 0;
1272 c->rc_buffer_size = 0;
1276 if (intra_matrix[0] == 0x08)
1277 c->intra_matrix = intra_matrix.data();
1279 c->qmin = c->qmax = 2;
1281 m_picture->width = info->sequence->width;
1282 m_picture->height = info->sequence->height;
1286 m_picture->pict_type = AV_PICTURE_TYPE_NONE;
1289 if (avcodec_open2(c, out_codec,
nullptr) < 0)
1291 LOG(VB_GENERAL, LOG_ERR,
"could not open codec");
1296 int ret = avcodec_send_frame(c,
m_picture);
1298 bool flushed =
false;
1302 ret = avcodec_receive_packet(c, pkt);
1305 if (ret == AVERROR(EAGAIN))
1312 ret = avcodec_send_frame(c,
nullptr);
1316 if (ret < 0 || !got_packet)
1318 LOG(VB_GENERAL, LOG_ERR,
1319 QString(
"avcodec_encode_video2 failed (%1)").arg(ret));
1323 if (!fname.isEmpty())
1325 QString ename = fname +
".enc";
1328 QString yname = fname +
".enc.yuv";
1335 int newSize = pkt->size - delta;
1336 pkt->pts = savedPts;
1337 memmove(pkt->data, pkt->data + delta, newSize);
1338 av_shrink_packet(pkt, newSize);
1341 SetRepeat(pkt->data, pkt->size, info->display_picture->nb_fields,
1342 ((info->display_picture->flags & PIC_FLAG_TOP_FIELD_FIRST) != 0U));
1344 avcodec_free_context(&c);
1356 static int s_frameCount = 0;
1359 LOG(VB_GENERAL, LOG_ERR,
"No more queue slots!");
1402 pkt->pts = AV_NOPTS_VALUE;
1403 pkt->dts = AV_NOPTS_VALUE;
1404 int ret = av_read_frame(
m_inputFC, pkt);
1415 LOG(VB_GENERAL, LOG_ERR,
1416 "Found end of file without finding any frames");
1417 av_packet_unref(pkt);
1422 if (tmpFrame ==
nullptr)
1424 av_packet_unref(pkt);
1434 if (pkt->stream_index ==
m_vidId ||
1435 m_aFrame.contains(pkt->stream_index))
1438 av_packet_unref(pkt);
1444 float percent_done = 100.0 * pkt->pos /
m_fileSize;
1448 LOG(VB_GENERAL, LOG_INFO, QString(
"%1% complete")
1449 .arg(percent_done, 0,
'f', 1));
1457 LOG(VB_DECODE, LOG_INFO, QString(
"Stream: %1 PTS: %2 DTS: %3 pos: %4")
1458 .arg(pkt->stream_index)
1459 .arg((pkt->pts == AV_NOPTS_VALUE) ?
"NONE" :
PtsTime(pkt->pts))
1460 .arg((pkt->dts == AV_NOPTS_VALUE) ?
"NONE" :
PtsTime(pkt->dts))
1465 if (tmpFrame ==
nullptr)
1467 av_packet_unref(pkt);
1471 switch (
m_inputFC->streams[pkt->stream_index]->codecpar->codec_type)
1473 case AVMEDIA_TYPE_VIDEO:
1475 av_packet_unref(pkt);
1482 case AVMEDIA_TYPE_AUDIO:
1483 if (
m_aFrame.contains(pkt->stream_index))
1485 m_aFrame[pkt->stream_index]->append(tmpFrame);
1489 LOG(VB_GENERAL, LOG_DEBUG,
1490 QString(
"Invalid stream ID %1, ignoring").arg(pkt->stream_index));
1493 av_packet_unref(pkt);
1498 av_packet_unref(pkt);
1506 QMap <int, bool> found;
1507 AVPacket *pkt = av_packet_alloc();
1510 LOG(VB_PROCESS, LOG_ERR,
"packet allocation failed");
1518 av_packet_free(&pkt);
1522 if (
m_vidId == pkt->stream_index)
1526 if (
m_vFrame.first()->m_isSequence)
1528 if (pkt->pos !=
m_vFrame.first()->m_pkt->pos)
1531 if (pkt->pts != AV_NOPTS_VALUE ||
1532 pkt->dts != AV_NOPTS_VALUE)
1534 if (pkt->pts == AV_NOPTS_VALUE)
1535 m_vFrame.first()->m_pkt->pts = pkt->dts;
1537 LOG(VB_PROCESS, LOG_INFO,
1538 "Found 1st valid video frame");
1543 LOG(VB_PROCESS, LOG_INFO,
"Dropping V packet");
1554 if (found.contains(it.key()))
1559 while (!af->isEmpty())
1561 int64_t delta =
diff2x33(af->first()->m_pkt->pts,
1563 if (delta < -180000 || delta > 180000)
1568 for (
auto *currFrame : qAsConst(
m_vFrame))
1570 if (currFrame->m_isSequence)
1572 int64_t dlta1 =
diff2x33(af->first()->m_pkt->pts,
1573 currFrame->m_pkt->pts);
1574 if (dlta1 >= -180000 && dlta1 <= 180000)
1576 foundframe = currFrame;
1583 while (foundframe &&
m_vFrame.first() != foundframe)
1589 if (delta < -180000 || delta > 180000)
1591 LOG(VB_PROCESS, LOG_INFO,
1592 QString(
"Dropping A packet from stream %1")
1594 LOG(VB_PROCESS, LOG_INFO, QString(
" A:%1 V:%2")
1595 .arg(
PtsTime(af->first()->m_pkt->pts),
1601 if (delta < 0 && af->count() > 1)
1603 if (
cmp2x33(af->at(1)->m_pkt->pts,
1606 LOG(VB_PROCESS, LOG_INFO,
1607 QString(
"Found useful audio frame from stream %1")
1609 found[it.key()] =
true;
1612 LOG(VB_PROCESS, LOG_INFO,
1613 QString(
"Dropping A packet from stream %1")
1620 LOG(VB_PROCESS, LOG_INFO,
1621 QString(
"Found useful audio frame from stream %1")
1623 found[it.key()] =
true;
1627 if (af->count() == 1)
1631 }
while (found.count() !=
m_aFrame.count());
1633 av_packet_free(&pkt);
1646 uint8_t *end = ptr + size;
1647 uint8_t setmask = 0x00;
1648 uint8_t clrmask = 0xff;
1661 if (
MATCH_HEADER(ptr) && ptr[3] == 0xB5 && (ptr[4] & 0xF0) == 0x80)
1676 for (
const auto & vf : qAsConst(
m_vFrame))
1689 for (
int pos = start_pos; pos < maxPos; pos++)
1730 bool skip_first =
false;
1745 int framePos =
m_vFrame.indexOf(spare);
1753 if (!skip_first && curPos >= framePos && info->display_picture &&
1754 (
int)info->display_picture->temporal_reference >= frameNum)
1766 int tmpFrameNum = frameNum;
1768 if (tmpFrame ==
nullptr)
1774 while (!info->display_picture ||
1775 (
int)info->display_picture->temporal_reference < frameNum)
1788 if ((
int)info->display_picture->temporal_reference > frameNum)
1794 LOG(VB_GENERAL, LOG_NOTICE,
1795 QString(
"Frame %1 > %2. Corruption likely at pos: %3")
1796 .arg(info->display_picture->temporal_reference)
1797 .arg(frameNum).arg(spare->
m_pkt->pos));
1806 AVPacket *pkt = av_packet_alloc();
1809 LOG(VB_PROCESS, LOG_ERR,
"packet allocation failed");
1813 static int ins_count = 0;
1821 av_packet_free(&pkt);
1826 for (
const auto & of : qAsConst(*orderedFrames))
1829 if ((spare =
DecodeToFrame(i,
static_cast<int>(headPos == 0))) ==
nullptr)
1831 LOG(VB_GENERAL, LOG_WARNING,
1832 QString(
"ConvertToI skipping undecoded frame #%1").arg(i));
1840 av_packet_ref(pkt, spare->
m_pkt);
1847 fname = QString(
"cnv%1").arg(ins_count++);
1852 av_packet_free(&pkt);
1856 LOG(VB_GENERAL, LOG_INFO,
1857 QString(
"Converting frame #%1 from %2 to I %3")
1861 av_packet_unref(pkt);
1867 m_vFrame.move(headPos, headPos + orderedFrames->count() - 1);
1868 av_packet_free(&pkt);
1873 int64_t ptsIncrement, int64_t initPTS)
1879 AVPacket *pkt = av_packet_alloc();
1882 LOG(VB_PROCESS, LOG_ERR,
"packet allocation failed");
1888 av_packet_free(&pkt);
1892 av_packet_ref(pkt, spare->
m_pkt);
1898 static int ins_count = 0;
1900 (QString(
"ins%1").arg(ins_count++)) : QString());
1905 av_packet_free(&pkt);
1909 LOG(VB_GENERAL, LOG_INFO,
1910 QString(
"Inserting %1 I-Frames after #%2 %3")
1911 .arg((
int)(deltaPTS / ptsIncrement))
1917 index =
m_vFrame.indexOf(spare) + 1;
1924 while (deltaPTS > 0)
1928 pkt->dts = pkt->pts;
1931 if (tmpFrame ==
nullptr)
1936 inc2x33(&pkt->pts, ptsIncrement);
1937 deltaPTS -= ptsIncrement;
1940 av_packet_free(&pkt);
1962 for (
const auto & range : qAsConst(rangelist))
1964 QStringList
tmp = range.split(
" - ");
1968 std::array<bool,2> ok {
false,
false };
1970 long long start =
tmp[0].toLongLong(ok.data());
1971 long long end =
tmp[1].toLongLong(&ok[1]);
1987 if (!rangelist.isEmpty())
1993 if (!mapPtr->isEmpty())
1996 frm_dir_map_t::iterator it = mapPtr->begin();
1997 for (; it != mapPtr->end(); ++it)
2000 msg += QString(
"\n\t\t%1 - %2").arg(start).arg(it.key());
2005 msg += QString(
"\n\t\t%1 - end").arg(start);
2006 LOG(VB_PROCESS, LOG_INFO, msg);
2013 int maxPos = dtsOrder->count() - 1;
2020 for (pos++; pos < maxPos &&
GetFrameTypeT(dtsOrder->at(pos)) ==
'B'; pos++)
2021 Lreorder.append(dtsOrder->at(pos));
2023 Lreorder.append(frame);
2028 int64_t &PTSdiscrep,
int numframes,
bool fix)
const
2033 if (curFrame->
m_pkt->pts == AV_NOPTS_VALUE)
2035 LOG(VB_PROCESS, LOG_INFO,
2036 QString(
"Found frame %1 with missing PTS at %2")
2038 .arg(
PtsTime(origvPTS / 300)));
2040 curFrame->
m_pkt->pts = origvPTS / 300;
2042 PTSdiscrep = AV_NOPTS_VALUE;
2047 if (tmpPTS != PTSdiscrep)
2049 PTSdiscrep = tmpPTS;
2050 LOG(VB_PROCESS, LOG_INFO,
2051 QString(
"Found invalid PTS (off by %1) at %2")
2056 curFrame->
m_pkt->pts = origvPTS / 300;
2060 origvPTS = curFrame->
m_pkt->pts * 300;
2062 ptsinc((uint64_t *)&origvPTS,
2068 LOG(VB_GENERAL, LOG_INFO,
"=========================================");
2069 LOG(VB_GENERAL, LOG_INFO, QString(
"List contains %1 items")
2070 .arg(list->count()));
2072 for (
auto *curFrame : qAsConst(*list))
2074 LOG(VB_GENERAL, LOG_INFO,
2075 QString(
"VID: %1 #:%2 nb: %3 pts: %4 dts: %5 pos: %6")
2079 .arg(
PtsTime(curFrame->m_pkt->pts),
2080 PtsTime(curFrame->m_pkt->dts),
2081 QString::number(curFrame->m_pkt->pos)));
2083 LOG(VB_GENERAL, LOG_INFO,
"=========================================");
2090 int64_t lastPTS = 0;
2091 int64_t deltaPTS = 0;
2092 std::array<int64_t,N_AUDIO> origaPTS {};
2093 int64_t cutStartPTS = 0;
2094 int64_t cutEndPTS = 0;
2095 uint64_t frame_count = 0;
2096 int new_discard_state = 0;
2097 QMap<int, int> af_dlta_cnt;
2098 QMap<int, int> cutState;
2100 AVPacket *pkt = av_packet_alloc();
2101 AVPacket *lastRealvPkt = av_packet_alloc();
2102 if ((pkt ==
nullptr) || (lastRealvPkt ==
nullptr))
2104 LOG(VB_GENERAL, LOG_ERR,
"packet allocation failed");
2110 av_packet_free(&pkt);
2111 av_packet_free(&lastRealvPkt);
2117 av_packet_free(&pkt);
2118 av_packet_free(&lastRealvPkt);
2124 int64_t initPTS =
m_vFrame.first()->m_pkt->pts;
2126 LOG(VB_GENERAL, LOG_INFO, QString(
"#%1 PTS:%2 Delta: 0.0ms queue: %3")
2133 deltaPTS =
diff2x33(
m_vFrame.first()->m_pkt->pts, af->first()->m_pkt->pts);
2134 LOG(VB_GENERAL, LOG_INFO,
2135 QString(
"#%1 PTS:%2 Delta: %3ms queue: %4")
2136 .arg(it.key()) .arg(
PtsTime(af->first()->m_pkt->pts))
2137 .arg(1000.0*deltaPTS / 90000.0).arg(af->count()));
2139 if (
cmp2x33(af->first()->m_pkt->pts, initPTS) < 0)
2140 initPTS = af->first()->m_pkt->pts;
2147 LOG(VB_PROCESS, LOG_INFO,
2148 QString(
"ptsIncrement: %1 Frame #: %2 PTS-adjust: %3")
2155 int64_t expectedvPTS = 300 * (
udiff2x33(
m_vFrame.first()->m_pkt->pts, initPTS) -
2161 cutStartPTS = origvPTS / 300;
2167 origaPTS[it.key()] = af->first()->m_pkt->pts * 300;
2169 af_dlta_cnt[it.key()] = 0;
2170 cutState[it.key()] =
static_cast<int>(
m_discard);
2184 av_packet_free(&pkt);
2185 av_packet_free(&lastRealvPkt);
2200 LOG(VB_GENERAL, LOG_WARNING,
2201 QString(
"Problem: Frame %1 (type %2) doesn't contain "
2208 LOG(VB_GENERAL, LOG_WARNING,
2209 QString(
"WARNING - Unsupported FPS change from %1 to %2")
2211 .arg(27000000.0 / seqFrame->
m_mpeg2_seq.frame_period,
2215 for (
int frame_pos = 0; frame_pos <
m_vFrame.count() - 1;)
2217 bool ptsorder_eq_dtsorder =
false;
2218 int64_t PTSdiscrep = 0;
2225 LOG(VB_GENERAL, LOG_ERR,
2226 QString(
"expectedPTS != expectedDTS + ptsIncrement"));
2227 LOG(VB_GENERAL, LOG_ERR, QString(
"%1 != %2 + %3")
2228 .arg(
PtsTime(expectedvPTS / 300),
2231 LOG(VB_GENERAL, LOG_ERR, QString(
"%1 != %2 + %3")
2235 av_packet_free(&pkt);
2236 av_packet_free(&lastRealvPkt);
2244 for (
auto *curFrame : qAsConst(Lreorder))
2258 int count = Lreorder.count();
2263 av_packet_free(&pkt);
2264 av_packet_free(&lastRealvPkt);
2271 int64_t tmp_origvPTS = origvPTS;
2275 (frame_pos + count + 1) <
m_vFrame.count())
2280 for (
auto *curFrame : qAsConst(tmpReorder))
2282 int64_t tmpPTSdiscrep = 0;
2284 tmpPTSdiscrep, numframes,
false);
2292 if (tmpPTSdiscrep != AV_NOPTS_VALUE &&
2293 tmpPTSdiscrep != PTSdiscrep)
2294 PTSdiscrep = tmpPTSdiscrep;
2296 count += tmpReorder.count();
2309 for (
int curIndex = 0; curIndex < Lreorder.count(); curIndex++)
2311 MPEG2frame *curFrame = Lreorder.at(curIndex);
2314 if (
m_saveMap.begin().key() <= frame_count)
2318 LOG(VB_GENERAL, LOG_INFO,
2319 QString(
"Saving frame #%1") .arg(frame_count));
2324 av_packet_free(&pkt);
2325 av_packet_free(&lastRealvPkt);
2329 WriteFrame(QString(
"save%1.yuv").arg(frame_count),
2336 new_discard_state =
m_delMap.begin().value();
2337 LOG(VB_GENERAL, LOG_INFO,
2338 QString(
"Del map found %1 at %2 (%3)")
2339 .arg(new_discard_state) .arg(frame_count)
2343 markedFrameP = curFrame;
2345 if (!new_discard_state)
2347 cutEndPTS = markedFrameP->
m_pkt->pts;
2349 diff2x33(cutEndPTS, expectedvPTS / 300),
2361 cutState[it3.key()] = 1;
2369 (!new_discard_state &&
2374 av_packet_free(&pkt);
2375 av_packet_free(&lastRealvPkt);
2378 ptsorder_eq_dtsorder =
true;
2380 else if (!new_discard_state &&
2383 m_vFrame.move(frame_pos, frame_pos + curIndex);
2384 ptsorder_eq_dtsorder =
true;
2388 markedFrame =
m_vFrame.at(frame_pos + curIndex);
2390 if (!new_discard_state)
2401 if (!Lreorder.isEmpty())
2403 av_packet_unref(lastRealvPkt);
2404 av_packet_ref(lastRealvPkt, Lreorder.last()->m_pkt);
2409 int64_t dtsExtra = 0;
2411 for (
auto *curFrame : qAsConst(Lreorder))
2415 if (curFrame != markedFrameP)
2418 markedFrameP =
nullptr;
2421 dec2x33(&curFrame->m_pkt->pts,
2423 deltaPTS =
diff2x33(curFrame->m_pkt->pts,
2424 expectedvPTS / 300);
2426 if (deltaPTS < -2 || deltaPTS > 2)
2428 LOG(VB_PROCESS, LOG_INFO,
2429 QString(
"PTS discrepancy: %1 != %2 on "
2431 .arg(curFrame->m_pkt->pts)
2432 .arg(expectedvPTS / 300)
2443 curFrame->m_pkt->pts = expectedvPTS / 300;
2447 LOG(VB_GENERAL, LOG_NOTICE,
2448 QString(
"Need to insert %1 frames > max "
2449 "allowed: %2. Assuming bad PTS")
2452 curFrame->m_pkt->pts = expectedvPTS / 300;
2456 lastPTS = expectedvPTS;
2460 if (curFrame == markedFrameP && new_discard_state)
2466 if (ptsorder_eq_dtsorder)
2479 m_vFrame.at(frame_pos)->m_pkt->pts = lastPTS / 300;
2485 av_packet_free(&pkt);
2486 av_packet_free(&lastRealvPkt);
2490 for (
int index = frame_pos + Lreorder.count();
2491 ret && index <
m_vFrame.count(); index++, --ret)
2493 lastPTS = expectedvPTS;
2496 Lreorder.append(
m_vFrame.at(index));
2503 for (
int i = 0; i < Lreorder.count(); i++, frame_pos++)
2508 if (curFrame != markedFrame)
2512 markedFrame =
nullptr;
2516 if (curFrame ==
nullptr)
2518 curFrame->
m_pkt->dts = (expectedDTS / 300);
2521 curFrame->
m_pkt->pts = (expectedDTS / 300);
2524 ((!ptsorder_eq_dtsorder && i == 0) ? 2 :
2526 LOG(VB_FRAME, LOG_INFO,
2527 QString(
"VID: %1 #:%2 nb: %3 pts: %4 dts: %5 "
2534 QString::number(curFrame->
m_pkt->pos)));
2537 av_packet_free(&pkt);
2538 av_packet_free(&lastRealvPkt);
2542 if (curFrame == markedFrame)
2544 markedFrame =
nullptr;
2549 expectedDTS += dtsExtra;
2553 frame_pos += Lreorder.count();
2557 PTSdiscrep), lastRealvPkt);
2561 cutEndPTS = lastRealvPkt->pts;
2574 bool backwardsPTS =
false;
2576 while (!af->isEmpty())
2585 if (CC->sample_rate == 0 || !CPC || CPC->duration == 0)
2600 90000LL * (int64_t)CPC->duration / CC->sample_rate;
2603 af->first()->m_pkt) < 0)
2605 backwardsPTS =
true;
2606 af_dlta_cnt[it.key()] = 0;
2609 int64_t tmpPTS =
diff2x33(af->first()->m_pkt->pts,
2610 origaPTS[it.key()] / 300);
2612 if (tmpPTS < -incPTS)
2615 LOG(VB_PROCESS, LOG_INFO,
2616 QString(
"Aud discard: PTS %1 < %2")
2617 .arg(
PtsTime(af->first()->m_pkt->pts))
2618 .arg(
PtsTime(origaPTS[it.key()] / 300)));
2621 af_dlta_cnt[it.key()] = 0;
2627 LOG(VB_PROCESS, LOG_INFO,
2628 QString(
"Found invalid audio PTS (off by %1) at %2")
2630 PtsTime(origaPTS[it.key()] / 300)));
2631 if (backwardsPTS && tmpPTS < 90000LL)
2634 LOG(VB_PROCESS, LOG_INFO,
2635 "Fixing missing audio frames");
2636 ptsinc((uint64_t *)&origaPTS[it.key()], 300 * tmpPTS);
2637 backwardsPTS =
false;
2639 else if (tmpPTS < 90000LL * 4)
2641 if (af_dlta_cnt[it.key()] >= 20)
2647 ptsinc((uint64_t *)&origaPTS[it.key()],
2649 af_dlta_cnt[it.key()] = 0;
2652 af_dlta_cnt[it.key()]++;
2654 af->first()->m_pkt->pts = origaPTS[it.key()] / 300;
2656 else if (tmpPTS > incPTS)
2659 backwardsPTS =
false;
2660 af_dlta_cnt[it.key()] = 0;
2664 backwardsPTS =
false;
2665 af_dlta_cnt[it.key()] = 0;
2668 int64_t nextPTS =
add2x33(af->first()->m_pkt->pts,
2669 90000LL * (int64_t)CPC->duration / CC->sample_rate);
2671 if ((cutState[it.key()] == 1 &&
2672 cmp2x33(nextPTS, cutStartPTS) > 0) ||
2673 (cutState[it.key()] == 2 &&
2674 cmp2x33(af->first()->m_pkt->pts, cutEndPTS) < 0))
2677 LOG(VB_PROCESS, LOG_INFO,
2678 QString(
"Aud in cutpoint: %1 > %2 && %3 < %4")
2680 .arg(
PtsTime(af->first()->m_pkt->pts))
2684 cutState[it.key()] = 2;
2685 ptsinc((uint64_t *)&origaPTS[it.key()], incPTS * 300);
2689 int64_t deltaPTS2 = poq.
Get(it.key(), af->first()->m_pkt);
2691 if (
udiff2x33(nextPTS, deltaPTS2) * 300 > expectedDTS &&
2692 cutState[it.key()] != 1)
2695 LOG(VB_PROCESS, LOG_INFO, QString(
"Aud not ready: %1 > %2")
2697 .arg(
PtsTime(expectedDTS / 300)));
2702 if (cutState[it.key()] == 2)
2703 cutState[it.key()] = 0;
2705 ptsinc((uint64_t *)&origaPTS[it.key()], incPTS * 300);
2707 dec2x33(&af->first()->m_pkt->pts, deltaPTS2);
2710 expectedPTS[it.key()] =
udiff2x33(nextPTS, initPTS);
2711 write_audio(lApkt_tail->m_pkt, initPTS);
2713 LOG(VB_FRAME, LOG_INFO, QString(
"AUD #%1: pts: %2 pos: %3")
2715 .arg(
PtsTime(af->first()->m_pkt->pts))
2716 .arg(af->first()->m_pkt->pos));
2719 av_packet_free(&pkt);
2720 av_packet_free(&lastRealvPkt);
2733 void *errors =
nullptr;
2735 if (*(
int *)errors) {
2736 LOG(VB_GENERAL, LOG_ERR,
2737 QString(
"joined thread failed with %1 write errors")
2738 .arg(*(
int *)errors));
2742 av_packet_free(&pkt);
2743 av_packet_free(&lastRealvPkt);
2754 fprintf(
stderr,
"%s usage:\n", s);
2755 fprintf(
stderr,
"\t--infile <file> -i <file> : Input mpg file\n");
2756 fprintf(
stderr,
"\t--outfile <file> -o <file> : Output mpg file\n");
2757 fprintf(
stderr,
"\t--dbg_lvl # -d # : Debug level\n");
2758 fprintf(
stderr,
"\t--maxframes # -m # : Max frames to insert at once (default=10)\n");
2759 fprintf(
stderr,
"\t--cutlist \"start - end\" -c : Apply a cutlist. Specify on e'-c' per cut\n");
2760 fprintf(
stderr,
"\t--no3to2 -t : Remove 3:2 pullup\n");
2761 fprintf(
stderr,
"\t--fixup -f : make PTS continuous\n");
2762 fprintf(
stderr,
"\t--ostream <dvd|ps> -e : Output stream type (defaults to ps)\n");
2763 fprintf(
stderr,
"\t--showprogress -p : show progress\n");
2764 fprintf(
stderr,
"\t--help -h : This screen\n");
2768 int main(
int argc,
char **argv)
2770 QStringList cutlist;
2771 QStringList savelist;
2772 char *infile =
nullptr, *outfile =
nullptr, *format =
nullptr;
2773 int no_repeat = 0, fix_PTS = 0, max_frames = 20, otype =
REPLEX_MPEG2;
2774 bool showprogress = 0;
2775 const struct option long_options[] =
2777 {
"infile", required_argument,
nullptr,
'i'},
2778 {
"outfile", required_argument,
nullptr,
'o'},
2779 {
"format", required_argument,
nullptr,
'r'},
2780 {
"dbg_lvl", required_argument,
nullptr,
'd'},
2781 {
"cutlist", required_argument,
nullptr,
'c'},
2782 {
"saveframe", required_argument,
nullptr,
's'},
2783 {
"ostream", required_argument,
nullptr,
'e'},
2784 {
"no3to2", no_argument,
nullptr,
't'},
2785 {
"fixup", no_argument,
nullptr,
'f'},
2786 {
"showprogress", no_argument,
nullptr,
'p'},
2787 {
"help", no_argument ,
nullptr,
'h'},
2793 int option_index = 0;
2795 c = getopt_long (argc, argv,
"i:o:d:r:m:c:s:e:tfph",
2796 long_options, &option_index);
2817 if (strlen(optarg) == 3 && strncmp(optarg,
"dvd", 3) == 0)
2826 max_frames = atoi(optarg);
2830 cutlist.append(optarg);
2841 savelist.append(optarg);
2845 showprogress =
true;
2857 if (infile ==
nullptr || outfile ==
nullptr)
2860 MPEG2fixup m2f(infile, outfile,
nullptr, format,
2861 no_repeat, fix_PTS, max_frames,
2862 showprogress, otype);
2864 if (cutlist.count())
2866 if (savelist.count())
2876 LOG(VB_GENERAL, LOG_INFO,
"Generating Keyframe Index");
2887 LOG(VB_GENERAL, LOG_INFO,
"Seek tables are not required for MKV");
2891 AVPacket *pkt = av_packet_alloc();
2894 LOG(VB_GENERAL, LOG_ERR,
"packet allocation failed");
2898 uint64_t totalDuration = 0;
2899 while (av_read_frame(
m_inputFC, pkt) >= 0)
2901 if (pkt->stream_index ==
m_vidId)
2903 if (pkt->flags & AV_PKT_FLAG_KEY)
2905 posMap[count] = pkt->pos;
2906 durMap[count] = totalDuration;
2915 av_q2d(
m_inputFC->streams[pkt->stream_index]->time_base) *
2916 pkt->duration * 1000;
2919 av_packet_unref(pkt);
2923 av_packet_free(&pkt);
2927 LOG(VB_GENERAL, LOG_NOTICE,
"Transcode Completed");