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, mpeg2_alloc_t reason)
54 char *buf = (
char *) malloc (size + 63 +
sizeof (
void **));
57 memset(buf, 0, size + 63 +
sizeof (
void **));
58 char *align_buf = buf + 63 +
sizeof (
void **);
59 align_buf -= (
long)align_buf & 63;
60 *(((
void **)align_buf) - 1) = buf;
68 static void my_av_print(
void *ptr,
int level,
const char* fmt, va_list vl)
72 static QString s_fullLine(
"");
74 if (level > AV_LOG_INFO)
77 s_fullLine += QString::vasprintf(fmt, vl);
78 if (s_fullLine.endsWith(
"\n"))
81 LOG(VB_GENERAL, LOG_INFO, s_fullLine);
82 s_fullLine = QString(
"");
94 return QString(
"%1%2:%3:%4.%5")
95 .arg(is_neg ?
"-" :
"")
96 .arg((
uint)(
pts / 90000.) / 3600, 2, 10, QChar(
'0'))
97 .arg(((
uint)(
pts / 90000.) % 3600) / 60, 2, 10, QChar(
'0'))
98 .arg(((
uint)(
pts / 90000.) % 3600) % 60, 2, 10, QChar(
'0'))
99 .arg(((((
uint)(
pts / 90.) % 3600000) % 60000) % 1000), 3, 10, QChar(
'0'));
103 m_mpeg2_seq(), m_mpeg2_gop(), m_mpeg2_pic()
105 m_pkt = av_packet_alloc();
106 av_new_packet(
m_pkt, size);
111 av_packet_free(&
m_pkt);
116 if (
m_pkt->size < size)
118 int oldSize =
m_pkt->size;
119 if ((av_grow_packet(
m_pkt, size -
m_pkt->size) < 0) ||
m_pkt->size < size)
121 LOG(VB_GENERAL, LOG_CRIT, QString(
"MPEG2frame::ensure_size(): "
122 "Failed to grow packet size "
123 "from %1 to %2, result was %3")
124 .arg(oldSize).arg(size)
133 av_packet_unref(
m_pkt);
134 av_packet_ref(
m_pkt, newpkt);
144 idx.newPTS = initPTS;
149 for (
const int key : qAsConst(
m_keyList))
155 QList<poq_idx_t>::iterator it;
156 int64_t value =
m_offset[idx].first().newPTS;
164 while (
m_offset[idx].count() > 1 && !done)
167 if (((
static_cast<int>((*it).type) == 0) &&
168 (pkt->pts >= (*it).pos_pts) ) ||
170 ((pkt->pos >= (*it).pos_pts) || (pkt->duration > (*it).framenum))))
173 value =
m_offset[idx].first().newPTS;
190 for (
const int key : qAsConst(
m_keyList))
200 idx.framenum = pkt->duration;
203 LOG(VB_FRAME, LOG_INFO, QString(
"Offset %1 -> %2 (%3) at %4")
206 PtsTime(delta), QString::number(pkt->pos)));
207 for (
const int key : qAsConst(
m_keyList))
212 m_orig[key].push_back(idx);
219 QList<poq_idx_t> *dltaList = &
m_orig[idx];
220 while (!dltaList->isEmpty() &&
221 (pkt->pos >= dltaList->first().pos_pts ||
222 pkt->duration > dltaList->first().framenum))
224 if (dltaList->first().newPTS >= 0)
225 ptsinc((uint64_t *)&origPTS, 300 * dltaList->first().newPTS);
227 ptsdec((uint64_t *)&origPTS, -300 * dltaList->first().newPTS);
228 delta += dltaList->first().newPTS;
229 dltaList->pop_front();
230 LOG(VB_PROCESS, LOG_INFO,
231 QString(
"Moving PTS offset of stream %1 by %2")
232 .arg(idx).arg(
PtsTime(delta)));
239 const char *fmt,
bool norp,
bool fixPTS,
int maxf,
240 bool showprog,
int otype,
void (*update_func)(
float),
242 : m_noRepeat(norp), m_fixPts(fixPTS), m_maxFrames(maxf),
243 m_infile(inf), m_format(fmt)
248 if (deleteMap && !deleteMap->isEmpty())
251 frm_dir_map_t::iterator it = deleteMap->begin();
252 for (; it != deleteMap->end(); ++it)
254 uint64_t
mark = it.key();
306 const QFileInfo finfo(inf);
334 while (!af->isEmpty())
348 {
return (ptr[0] == 0x00) && (ptr[1] == 0x00) && (ptr[2] == 0x01); };
350 static void SETBITS(
unsigned char *ptr,
long value,
int num)
352 static int s_sbPos = 0;
353 static unsigned char *s_sbPtr =
nullptr;
361 if (s_sbPtr ==
nullptr)
364 int offset = s_sbPos >> 3;
365 int offset_r = s_sbPos & 0x07;
366 int offset_b = 32 - offset_r;
367 uint32_t mask = ~(((1 << num) - 1) << (offset_b - num));
368 uint32_t sb_long = ntohl(*((uint32_t *) (s_sbPtr + offset)));
369 value = value << (offset_b - num);
370 sb_long = (sb_long & mask) + value;
371 *((uint32_t *)(s_sbPtr + offset)) = htonl(sb_long);
381 *pts1 = (*pts1 + pts2) %
MAX_PTS;
386 int64_t diff = pts1 - pts2;
405 return (pts1 - pts2);
409 return (pts1 +
MAX_PTS - pts2);
413 return (pts1 - (pts2 +
MAX_PTS));
422 int64_t
tmp = pts1 + pts2;
424 return (pts1 + pts2) %
MAX_PTS;
434 if ((uint64_t)(pts1 - pts2) >
MAX_PTS/2ULL)
439 else if (pts1 == pts2)
443 if ((uint64_t)(pts2 - pts1) >
MAX_PTS/2ULL)
453 for (
int i = 0; i < size; i++)
473 return (rx->WaitBuffers());
494 pthread_mutex_lock( &
m_mutex );
509 pthread_cond_signal(&
m_cond);
512 pthread_mutex_unlock(&
m_mutex);
518 static int errorcount = 0;
521 LOG(VB_GENERAL, LOG_ERR,
522 QString(
"thread finished with %1 write errors")
525 pthread_exit(&errorcount);
560 mx.
priv = (
void *)
this;
562 int fd_out = open(
m_outfile.toLocal8Bit().constData(),
567 pthread_cond_signal(&
m_cond);
569 pthread_mutex_unlock(&
m_mutex);
592 #define INDEX_BUF (sizeof(index_unit) * 200)
599 if (
m_vFrame.first()->m_mpeg2_seq.height >= 720)
601 LOG(VB_GENERAL, LOG_NOTICE,
"MPEG2fixup::InitReplex(): High Definition input, increasing replex buffers");
608 LOG(VB_GENERAL, LOG_WARNING,
"MPEG2fixup::InitReplex(): Using '--ostream=dvd' with HD video is an invalid combination");
613 uint32_t memsize =
m_vFrame.first()->m_mpeg2_seq.width *
614 m_vFrame.first()->m_mpeg2_seq.height * 10;
626 uint index = it.key();
630 if (avctx ==
nullptr)
633 AVDictionaryEntry *metatag =
634 av_dict_get(
m_inputFC->streams[index]->metadata,
635 "language",
nullptr, 0);
636 char *lang = metatag ? metatag->value : (
char *)
"";
645 case AV_CODEC_ID_MP2:
646 case AV_CODEC_ID_MP3:
650 case AV_CODEC_ID_AC3:
660 26999999ULL) /
m_vFrame.first()->m_mpeg2_seq.frame_period;
667 QString msg = QString(
"Id:%1 %2 V:%3").arg(f->
m_pkt->stream_index)
675 msg += QString(
" %2")
678 LOG(VB_RPLXQUEUE, LOG_INFO, msg);
686 int id = f->
m_pkt->stream_index;
697 iu.gop =
static_cast<uint8_t
>(f->
m_isGop);
701 iu.dts = f->
m_pkt->dts * 300;
709 iu.framesize = f->
m_pkt->size;
714 LOG(VB_GENERAL, LOG_ERR,
"Ringbuffer pointers empty. No stream found");
719 iu.length = f->
m_pkt->size;
720 iu.pts = f->
m_pkt->pts * 300;
744 unsigned int inc_size = 10 * (
unsigned int)f->
m_pkt->size;
745 LOG(VB_GENERAL, LOG_NOTICE,
746 QString(
"Increasing ringbuffer size by %1 to avoid deadlock")
756 LOG(VB_GENERAL, LOG_ERR,
757 "Deadlock detected. One buffer is full when "
758 "the other is empty! Aborting");
771 LOG(VB_GENERAL, LOG_ERR,
772 QString(
"Ring buffer overflow %1").arg(rb->
size));
779 LOG(VB_GENERAL, LOG_ERR,
780 QString(
"Ring buffer overflow %1").arg(rbi->
size));
790 QByteArray ifarray = inputfile.toLocal8Bit();
791 const char *ifname = ifarray.constData();
793 const AVInputFormat *fmt =
nullptr;
796 fmt = av_find_input_format(
type);
799 LOG(VB_GENERAL, LOG_INFO, QString(
"Opening %1").arg(inputfile));
807 int ret = avformat_open_input(&
m_inputFC, ifname, fmt,
nullptr);
810 LOG(VB_GENERAL, LOG_ERR,
811 QString(
"Couldn't open input file, error #%1").arg(ret));
818 fmt = av_find_input_format(
"mpegts-ffmpeg");
821 LOG(VB_PLAYBACK, LOG_INFO,
"Using FFmpeg MPEG-TS demuxer (forced)");
823 ret = avformat_open_input(&
m_inputFC, ifname, fmt,
nullptr);
826 LOG(VB_GENERAL, LOG_ERR,
827 QString(
"Couldn't open input file, error #%1").arg(ret));
839 ret = avformat_find_stream_info(
m_inputFC,
nullptr);
842 LOG(VB_GENERAL, LOG_ERR,
843 QString(
"Couldn't get stream info, error #%1").arg(ret));
853 for (
unsigned int i = 0; i <
m_inputFC->nb_streams; i++)
855 switch (
m_inputFC->streams[i]->codecpar->codec_type)
857 case AVMEDIA_TYPE_VIDEO:
862 case AVMEDIA_TYPE_AUDIO:
864 m_inputFC->streams[i]->codecpar->ch_layout.nb_channels < 2 &&
865 m_inputFC->streams[i]->codecpar->sample_rate < 100000)
867 LOG(VB_GENERAL, LOG_ERR,
868 QString(
"Skipping audio stream: %1").arg(i));
871 if (
m_inputFC->streams[i]->codecpar->codec_id == AV_CODEC_ID_AC3 ||
872 m_inputFC->streams[i]->codecpar->codec_id == AV_CODEC_ID_MP3 ||
873 m_inputFC->streams[i]->codecpar->codec_id == AV_CODEC_ID_MP2)
880 LOG(VB_GENERAL, LOG_ERR,
881 QString(
"Skipping unsupported audio stream: %1")
882 .arg(
m_inputFC->streams[i]->codecpar->codec_id));
886 LOG(VB_GENERAL, LOG_ERR,
887 QString(
"Skipping unsupported codec %1 on stream %2")
888 .arg(
m_inputFC->streams[i]->codecpar->codec_type).arg(i));
908 int oldPktSize = frame1->
m_pkt->size;
910 memmove(frame1->
m_pkt->data + head_size, frame1->
m_pkt->data, oldPktSize);
911 memcpy(frame1->
m_pkt->data, frame2->
m_pkt->data, head_size);
916 static int count = 0;
917 QString
filename = QString(
"hdr%1.yuv").arg(count++);
935 auto *info = (mpeg2_info_t *)mpeg2_info(dec);
939 while (state != STATE_PICTURE)
941 state = mpeg2_parse(dec);
949 case STATE_SEQUENCE_MODIFIED:
950 case STATE_SEQUENCE_REPEATED:
952 sizeof(mpeg2_sequence_t));
957 memcpy(&vf->
m_mpeg2_gop, info->gop,
sizeof(mpeg2_gop_t));
965 sizeof(mpeg2_picture_t));
970 LOG(VB_GENERAL, LOG_WARNING,
971 "Warning: partial frame found!");
975 else if (state == STATE_BUFFER)
978 LOG(VB_GENERAL, LOG_ERR,
979 QString(
"Failed to decode frame. Position was: %1")
983 last_pos = (vf->
m_pkt->size - mpeg2_getpos(dec)) - 4;
988 while (state != STATE_BUFFER)
989 state = mpeg2_parse(dec);
990 if (info->display_picture)
997 std::array<uint8_t,8>
tmp {0x00, 0x00, 0x01, 0xb2, 0xff, 0xff, 0xff, 0xff};
998 mpeg2_buffer(dec,
tmp.data(),
tmp.data() + 8);
1005 QString msg = QString(
"");
1007 msg += QString(
"unused:%1 ") .arg(vf->
m_pkt->size - mpeg2_getpos(dec));
1011 msg += QString(
"%1x%2 P:%3 ").arg(info->sequence->width)
1012 .arg(info->sequence->height).arg(info->sequence->frame_period);
1016 QString gop = QString(
"%1:%2:%3:%4 ")
1017 .arg(info->gop->hours, 2, 10, QChar(
'0')).arg(info->gop->minutes, 2, 10, QChar(
'0'))
1018 .arg(info->gop->seconds, 2, 10, QChar(
'0')).arg(info->gop->pictures, 3, 10, QChar(
'0'));
1021 if (info->current_picture)
1023 int ct = info->current_picture->flags & PIC_MASK_CODING_TYPE;
1024 char coding_type = (ct == PIC_FLAG_CODING_TYPE_I) ?
'I' :
1025 ((ct == PIC_FLAG_CODING_TYPE_P) ?
'P' :
1026 ((ct == PIC_FLAG_CODING_TYPE_B) ?
'B' :
1027 ((ct == PIC_FLAG_CODING_TYPE_D) ?
'D' :
'X')));
1028 char top_bottom = (info->current_picture->flags &
1029 PIC_FLAG_TOP_FIELD_FIRST) ?
'T' :
'B';
1030 char progressive = (info->current_picture->flags &
1031 PIC_FLAG_PROGRESSIVE_FRAME) ?
'P' :
'_';
1032 msg += QString(
"#%1 fl:%2%3%4%5%6 ")
1033 .arg(info->current_picture->temporal_reference)
1034 .arg(info->current_picture->nb_fields)
1038 .arg(info->current_picture->flags >> 4, 0, 16);
1040 msg += QString(
"pos: %1").arg(vf->
m_pkt->pos);
1041 LOG(VB_DECODE, LOG_INFO, msg);
1050 if (tmpFrame ==
nullptr)
1054 for (
const auto & vf : qAsConst(
m_vFrame))
1056 if (vf->m_isSequence)
1070 if (tmpFrame ==
nullptr)
1076 mpeg2dec_t *tmp_decoder = mpeg2_init();
1077 auto *info = (mpeg2_info_t *)mpeg2_info(tmp_decoder);
1079 while (!info->display_picture)
1090 mpeg2_close(tmp_decoder);
1095 int fh = open(
filename.toLocal8Bit().constData(),
1096 O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
1099 LOG(VB_GENERAL, LOG_ERR,
1100 QString(
"Couldn't open file %1: ").arg(
filename) +
ENO);
1104 int ret =
write(fh, info->display_fbuf->buf[0],
1105 info->sequence->width * info->sequence->height);
1108 LOG(VB_GENERAL, LOG_ERR, QString(
"write failed %1: ").arg(
filename) +
1112 ret =
write(fh, info->display_fbuf->buf[1],
1113 info->sequence->chroma_width * info->sequence->chroma_height);
1116 LOG(VB_GENERAL, LOG_ERR, QString(
"write failed %1: ").arg(
filename) +
1120 ret =
write(fh, info->display_fbuf->buf[2],
1121 info->sequence->chroma_width * 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");