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 ssize_t ret =
write(fh, info->display_fbuf->buf[0],
1105 static_cast<size_t>(info->sequence->width) *
1106 static_cast<size_t>(info->sequence->height));
1109 LOG(VB_GENERAL, LOG_ERR, QString(
"write failed %1: ").arg(
filename) +
1113 ret =
write(fh, info->display_fbuf->buf[1],
1114 static_cast<size_t>(info->sequence->chroma_width) *
1115 static_cast<size_t>(info->sequence->chroma_height));
1118 LOG(VB_GENERAL, LOG_ERR, QString(
"write failed %1: ").arg(
filename) +
1122 ret =
write(fh, info->display_fbuf->buf[2],
1123 static_cast<size_t>(info->sequence->chroma_width) *
1124 static_cast<size_t>(info->sequence->chroma_height));
1127 LOG(VB_GENERAL, LOG_ERR, QString(
"write failed %1: ").arg(
filename) +
1137 int fh = open(
filename.toLocal8Bit().constData(),
1138 O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
1141 LOG(VB_GENERAL, LOG_ERR,
1142 QString(
"Couldn't open file %1: ").arg(
filename) +
ENO);
1146 int ret =
write(fh, data, size);
1148 LOG(VB_GENERAL, LOG_ERR, QString(
"write failed %1").arg(
filename) +
1155 alignas(16) std::array<uint16_t,64> intra_matrix {};
1156 int64_t savedPts = pkt->pts;
1159 if (!info->display_fbuf)
1162 int outbuf_size = info->sequence->width * info->sequence->height * 2;
1164 if (!fname.isEmpty())
1166 QString tmpstr = fname +
".yuv";
1183 if (pkt->size < outbuf_size)
1184 av_grow_packet(pkt, (outbuf_size - pkt->size));
1186 m_picture->data[0] = info->display_fbuf->buf[0];
1187 m_picture->data[1] = info->display_fbuf->buf[1];
1188 m_picture->data[2] = info->display_fbuf->buf[2];
1190 m_picture->linesize[0] = info->sequence->width;
1191 m_picture->linesize[1] = info->sequence->chroma_width;
1192 m_picture->linesize[2] = info->sequence->chroma_width;
1194 m_picture->opaque = info->display_fbuf->id;
1197 static constexpr std::array<uint8_t, 64> k_zigzag_scan = {
1198 0, 1, 8, 16, 9, 2, 3, 10,
1199 17, 24, 32, 25, 18, 11, 4, 5,
1200 12, 19, 26, 33, 40, 48, 41, 34,
1201 27, 20, 13, 6, 7, 14, 21, 28,
1202 35, 42, 49, 56, 57, 50, 43, 36,
1203 29, 22, 15, 23, 30, 37, 44, 51,
1204 58, 59, 52, 45, 38, 31, 39, 46,
1205 53, 60, 61, 54, 47, 55, 62, 63
1208 static std::array<uint16_t, 64> k_invZigzagDirect16 = {};
1209 for (
int i = 0; i < 64; i++)
1211 k_invZigzagDirect16[k_zigzag_scan[i]] = i;
1214 static constexpr std::array<uint16_t, 64> k_invZigzagDirect16 = {
1215 0, 1, 5, 6, 14, 15, 27, 28,
1216 2, 4, 7, 13, 16, 26, 29, 42,
1217 3, 8, 12, 17, 25, 30, 41, 43,
1218 9, 11, 18, 24, 31, 40, 44, 53,
1219 10, 19, 23, 32, 39, 45, 52, 54,
1220 20, 22, 33, 38, 46, 51, 55, 60,
1221 21, 34, 37, 47, 50, 56, 59, 61,
1222 35, 36, 48, 49, 57, 58, 62, 63,
1226 for (
int i = 0; i < 64; i++)
1228 intra_matrix[k_invZigzagDirect16[i]] =
m_imgDecoder->quantizer_matrix[0][i];
1231 if (info->display_picture->nb_fields % 2)
1233 m_picture->top_field_first = ((info->display_picture->flags &
1234 PIC_FLAG_TOP_FIELD_FIRST) != 0) ? 0 : 1;
1238 m_picture->top_field_first = ((info->display_picture->flags &
1239 PIC_FLAG_TOP_FIELD_FIRST) != 0) ? 1 : 0;
1242 m_picture->interlaced_frame = ((info->display_picture->flags &
1243 PIC_FLAG_PROGRESSIVE_FRAME) != 0) ? 0 : 1;
1245 const AVCodec *out_codec = avcodec_find_encoder(AV_CODEC_ID_MPEG2VIDEO);
1248 LOG(VB_GENERAL, LOG_ERR,
"Couldn't find MPEG2 encoder");
1252 AVCodecContext *c = avcodec_alloc_context3(
nullptr);
1259 c->flags |= AV_CODEC_FLAG_INTERLACED_DCT;
1261 c->bit_rate = info->sequence->byte_rate << 3;
1262 c->bit_rate_tolerance = c->bit_rate >> 2;
1263 c->width = info->sequence->width;
1264 c->height = info->sequence->height;
1265 av_reduce(&c->time_base.num, &c->time_base.den,
1266 info->sequence->frame_period, 27000000LL, 100000);
1267 c->pix_fmt = AV_PIX_FMT_YUV420P;
1268 c->max_b_frames = 0;
1269 c->has_b_frames = 0;
1275 c->rc_buffer_size = 0;
1279 if (intra_matrix[0] == 0x08)
1280 c->intra_matrix = intra_matrix.data();
1282 c->qmin = c->qmax = 2;
1284 m_picture->width = info->sequence->width;
1285 m_picture->height = info->sequence->height;
1289 m_picture->pict_type = AV_PICTURE_TYPE_NONE;
1292 if (avcodec_open2(c, out_codec,
nullptr) < 0)
1294 LOG(VB_GENERAL, LOG_ERR,
"could not open codec");
1299 int ret = avcodec_send_frame(c,
m_picture);
1301 bool flushed =
false;
1305 ret = avcodec_receive_packet(c, pkt);
1308 if (ret == AVERROR(EAGAIN))
1315 ret = avcodec_send_frame(c,
nullptr);
1319 if (ret < 0 || !got_packet)
1321 LOG(VB_GENERAL, LOG_ERR,
1322 QString(
"avcodec_encode_video2 failed (%1)").arg(ret));
1326 if (!fname.isEmpty())
1328 QString ename = fname +
".enc";
1331 QString yname = fname +
".enc.yuv";
1338 int newSize = pkt->size - delta;
1339 pkt->pts = savedPts;
1340 memmove(pkt->data, pkt->data + delta, newSize);
1341 av_shrink_packet(pkt, newSize);
1344 SetRepeat(pkt->data, pkt->size, info->display_picture->nb_fields,
1345 ((info->display_picture->flags & PIC_FLAG_TOP_FIELD_FIRST) != 0U));
1347 avcodec_free_context(&c);
1359 static int s_frameCount = 0;
1362 LOG(VB_GENERAL, LOG_ERR,
"No more queue slots!");
1405 pkt->pts = AV_NOPTS_VALUE;
1406 pkt->dts = AV_NOPTS_VALUE;
1407 int ret = av_read_frame(
m_inputFC, pkt);
1418 LOG(VB_GENERAL, LOG_ERR,
1419 "Found end of file without finding any frames");
1420 av_packet_unref(pkt);
1425 if (tmpFrame ==
nullptr)
1427 av_packet_unref(pkt);
1437 if (pkt->stream_index ==
m_vidId ||
1438 m_aFrame.contains(pkt->stream_index))
1441 av_packet_unref(pkt);
1447 float percent_done = 100.0 * pkt->pos /
m_fileSize;
1451 LOG(VB_GENERAL, LOG_INFO, QString(
"%1% complete")
1452 .arg(percent_done, 0,
'f', 1));
1460 LOG(VB_DECODE, LOG_INFO, QString(
"Stream: %1 PTS: %2 DTS: %3 pos: %4")
1461 .arg(pkt->stream_index)
1462 .arg((pkt->pts == AV_NOPTS_VALUE) ?
"NONE" :
PtsTime(pkt->pts))
1463 .arg((pkt->dts == AV_NOPTS_VALUE) ?
"NONE" :
PtsTime(pkt->dts))
1468 if (tmpFrame ==
nullptr)
1470 av_packet_unref(pkt);
1474 switch (
m_inputFC->streams[pkt->stream_index]->codecpar->codec_type)
1476 case AVMEDIA_TYPE_VIDEO:
1478 av_packet_unref(pkt);
1485 case AVMEDIA_TYPE_AUDIO:
1486 if (
m_aFrame.contains(pkt->stream_index))
1488 m_aFrame[pkt->stream_index]->append(tmpFrame);
1492 LOG(VB_GENERAL, LOG_DEBUG,
1493 QString(
"Invalid stream ID %1, ignoring").arg(pkt->stream_index));
1496 av_packet_unref(pkt);
1501 av_packet_unref(pkt);
1509 QMap <int, bool> found;
1510 AVPacket *pkt = av_packet_alloc();
1513 LOG(VB_PROCESS, LOG_ERR,
"packet allocation failed");
1521 av_packet_free(&pkt);
1525 if (
m_vidId == pkt->stream_index)
1529 if (
m_vFrame.first()->m_isSequence)
1531 if (pkt->pos !=
m_vFrame.first()->m_pkt->pos)
1534 if (pkt->pts != AV_NOPTS_VALUE ||
1535 pkt->dts != AV_NOPTS_VALUE)
1537 if (pkt->pts == AV_NOPTS_VALUE)
1538 m_vFrame.first()->m_pkt->pts = pkt->dts;
1540 LOG(VB_PROCESS, LOG_INFO,
1541 "Found 1st valid video frame");
1546 LOG(VB_PROCESS, LOG_INFO,
"Dropping V packet");
1557 if (found.contains(it.key()))
1562 while (!af->isEmpty())
1564 int64_t delta =
diff2x33(af->first()->m_pkt->pts,
1566 if (delta < -180000 || delta > 180000)
1571 for (
auto *currFrame : qAsConst(
m_vFrame))
1573 if (currFrame->m_isSequence)
1575 int64_t dlta1 =
diff2x33(af->first()->m_pkt->pts,
1576 currFrame->m_pkt->pts);
1577 if (dlta1 >= -180000 && dlta1 <= 180000)
1579 foundframe = currFrame;
1586 while (foundframe &&
m_vFrame.first() != foundframe)
1592 if (delta < -180000 || delta > 180000)
1594 LOG(VB_PROCESS, LOG_INFO,
1595 QString(
"Dropping A packet from stream %1")
1597 LOG(VB_PROCESS, LOG_INFO, QString(
" A:%1 V:%2")
1598 .arg(
PtsTime(af->first()->m_pkt->pts),
1604 if (delta < 0 && af->count() > 1)
1606 if (
cmp2x33(af->at(1)->m_pkt->pts,
1609 LOG(VB_PROCESS, LOG_INFO,
1610 QString(
"Found useful audio frame from stream %1")
1612 found[it.key()] =
true;
1615 LOG(VB_PROCESS, LOG_INFO,
1616 QString(
"Dropping A packet from stream %1")
1623 LOG(VB_PROCESS, LOG_INFO,
1624 QString(
"Found useful audio frame from stream %1")
1626 found[it.key()] =
true;
1630 if (af->count() == 1)
1634 }
while (found.count() !=
m_aFrame.count());
1636 av_packet_free(&pkt);
1649 uint8_t *end = ptr + size;
1650 uint8_t setmask = 0x00;
1651 uint8_t clrmask = 0xff;
1664 if (
MATCH_HEADER(ptr) && ptr[3] == 0xB5 && (ptr[4] & 0xF0) == 0x80)
1679 for (
const auto & vf : qAsConst(
m_vFrame))
1692 for (
int pos = start_pos; pos < maxPos; pos++)
1733 bool skip_first =
false;
1748 int framePos =
m_vFrame.indexOf(spare);
1756 if (!skip_first && curPos >= framePos && info->display_picture &&
1757 (
int)info->display_picture->temporal_reference >= frameNum)
1769 int tmpFrameNum = frameNum;
1771 if (tmpFrame ==
nullptr)
1777 while (!info->display_picture ||
1778 (
int)info->display_picture->temporal_reference < frameNum)
1791 if ((
int)info->display_picture->temporal_reference > frameNum)
1797 LOG(VB_GENERAL, LOG_NOTICE,
1798 QString(
"Frame %1 > %2. Corruption likely at pos: %3")
1799 .arg(info->display_picture->temporal_reference)
1800 .arg(frameNum).arg(spare->
m_pkt->pos));
1809 AVPacket *pkt = av_packet_alloc();
1812 LOG(VB_PROCESS, LOG_ERR,
"packet allocation failed");
1816 static int ins_count = 0;
1824 av_packet_free(&pkt);
1829 for (
const auto & of : qAsConst(*orderedFrames))
1832 if ((spare =
DecodeToFrame(i,
static_cast<int>(headPos == 0))) ==
nullptr)
1834 LOG(VB_GENERAL, LOG_WARNING,
1835 QString(
"ConvertToI skipping undecoded frame #%1").arg(i));
1843 av_packet_ref(pkt, spare->
m_pkt);
1850 fname = QString(
"cnv%1").arg(ins_count++);
1855 av_packet_free(&pkt);
1859 LOG(VB_GENERAL, LOG_INFO,
1860 QString(
"Converting frame #%1 from %2 to I %3")
1864 av_packet_unref(pkt);
1870 m_vFrame.move(headPos, headPos + orderedFrames->count() - 1);
1871 av_packet_free(&pkt);
1876 int64_t ptsIncrement, int64_t initPTS)
1882 AVPacket *pkt = av_packet_alloc();
1885 LOG(VB_PROCESS, LOG_ERR,
"packet allocation failed");
1891 av_packet_free(&pkt);
1895 av_packet_ref(pkt, spare->
m_pkt);
1901 static int ins_count = 0;
1903 (QString(
"ins%1").arg(ins_count++)) : QString());
1908 av_packet_free(&pkt);
1912 LOG(VB_GENERAL, LOG_INFO,
1913 QString(
"Inserting %1 I-Frames after #%2 %3")
1914 .arg((
int)(deltaPTS / ptsIncrement))
1920 index =
m_vFrame.indexOf(spare) + 1;
1927 while (deltaPTS > 0)
1931 pkt->dts = pkt->pts;
1934 if (tmpFrame ==
nullptr)
1939 inc2x33(&pkt->pts, ptsIncrement);
1940 deltaPTS -= ptsIncrement;
1943 av_packet_free(&pkt);
1965 for (
const auto & range : qAsConst(rangelist))
1967 QStringList
tmp = range.split(
" - ");
1971 std::array<bool,2> ok {
false,
false };
1973 long long start =
tmp[0].toLongLong(ok.data());
1974 long long end =
tmp[1].toLongLong(&ok[1]);
1990 if (!rangelist.isEmpty())
1996 if (!mapPtr->isEmpty())
1999 frm_dir_map_t::iterator it = mapPtr->begin();
2000 for (; it != mapPtr->end(); ++it)
2003 msg += QString(
"\n\t\t%1 - %2").arg(start).arg(it.key());
2008 msg += QString(
"\n\t\t%1 - end").arg(start);
2009 LOG(VB_PROCESS, LOG_INFO, msg);
2016 int maxPos = dtsOrder->count() - 1;
2023 for (pos++; pos < maxPos &&
GetFrameTypeT(dtsOrder->at(pos)) ==
'B'; pos++)
2024 Lreorder.append(dtsOrder->at(pos));
2026 Lreorder.append(frame);
2031 int64_t &PTSdiscrep,
int numframes,
bool fix)
const
2036 if (curFrame->
m_pkt->pts == AV_NOPTS_VALUE)
2038 LOG(VB_PROCESS, LOG_INFO,
2039 QString(
"Found frame %1 with missing PTS at %2")
2041 .arg(
PtsTime(origvPTS / 300)));
2043 curFrame->
m_pkt->pts = origvPTS / 300;
2045 PTSdiscrep = AV_NOPTS_VALUE;
2050 if (tmpPTS != PTSdiscrep)
2052 PTSdiscrep = tmpPTS;
2053 LOG(VB_PROCESS, LOG_INFO,
2054 QString(
"Found invalid PTS (off by %1) at %2")
2059 curFrame->
m_pkt->pts = origvPTS / 300;
2063 origvPTS = curFrame->
m_pkt->pts * 300;
2065 ptsinc((uint64_t *)&origvPTS,
2071 LOG(VB_GENERAL, LOG_INFO,
"=========================================");
2072 LOG(VB_GENERAL, LOG_INFO, QString(
"List contains %1 items")
2073 .arg(list->count()));
2075 for (
auto *curFrame : qAsConst(*list))
2077 LOG(VB_GENERAL, LOG_INFO,
2078 QString(
"VID: %1 #:%2 nb: %3 pts: %4 dts: %5 pos: %6")
2082 .arg(
PtsTime(curFrame->m_pkt->pts),
2083 PtsTime(curFrame->m_pkt->dts),
2084 QString::number(curFrame->m_pkt->pos)));
2086 LOG(VB_GENERAL, LOG_INFO,
"=========================================");
2093 int64_t lastPTS = 0;
2094 int64_t deltaPTS = 0;
2095 std::array<int64_t,N_AUDIO> origaPTS {};
2096 int64_t cutStartPTS = 0;
2097 int64_t cutEndPTS = 0;
2098 uint64_t frame_count = 0;
2099 int new_discard_state = 0;
2100 QMap<int, int> af_dlta_cnt;
2101 QMap<int, int> cutState;
2103 AVPacket *pkt = av_packet_alloc();
2104 AVPacket *lastRealvPkt = av_packet_alloc();
2105 if ((pkt ==
nullptr) || (lastRealvPkt ==
nullptr))
2107 LOG(VB_GENERAL, LOG_ERR,
"packet allocation failed");
2113 av_packet_free(&pkt);
2114 av_packet_free(&lastRealvPkt);
2120 av_packet_free(&pkt);
2121 av_packet_free(&lastRealvPkt);
2127 int64_t initPTS =
m_vFrame.first()->m_pkt->pts;
2129 LOG(VB_GENERAL, LOG_INFO, QString(
"#%1 PTS:%2 Delta: 0.0ms queue: %3")
2136 deltaPTS =
diff2x33(
m_vFrame.first()->m_pkt->pts, af->first()->m_pkt->pts);
2137 LOG(VB_GENERAL, LOG_INFO,
2138 QString(
"#%1 PTS:%2 Delta: %3ms queue: %4")
2139 .arg(it.key()) .arg(
PtsTime(af->first()->m_pkt->pts))
2140 .arg(1000.0*deltaPTS / 90000.0).arg(af->count()));
2142 if (
cmp2x33(af->first()->m_pkt->pts, initPTS) < 0)
2143 initPTS = af->first()->m_pkt->pts;
2150 LOG(VB_PROCESS, LOG_INFO,
2151 QString(
"ptsIncrement: %1 Frame #: %2 PTS-adjust: %3")
2158 int64_t expectedvPTS = 300 * (
udiff2x33(
m_vFrame.first()->m_pkt->pts, initPTS) -
2164 cutStartPTS = origvPTS / 300;
2170 origaPTS[it.key()] = af->first()->m_pkt->pts * 300;
2172 af_dlta_cnt[it.key()] = 0;
2173 cutState[it.key()] =
static_cast<int>(
m_discard);
2187 av_packet_free(&pkt);
2188 av_packet_free(&lastRealvPkt);
2203 LOG(VB_GENERAL, LOG_WARNING,
2204 QString(
"Problem: Frame %1 (type %2) doesn't contain "
2211 LOG(VB_GENERAL, LOG_WARNING,
2212 QString(
"WARNING - Unsupported FPS change from %1 to %2")
2214 .arg(27000000.0 / seqFrame->
m_mpeg2_seq.frame_period,
2218 for (
int frame_pos = 0; frame_pos <
m_vFrame.count() - 1;)
2220 bool ptsorder_eq_dtsorder =
false;
2221 int64_t PTSdiscrep = 0;
2228 LOG(VB_GENERAL, LOG_ERR,
2229 QString(
"expectedPTS != expectedDTS + ptsIncrement"));
2230 LOG(VB_GENERAL, LOG_ERR, QString(
"%1 != %2 + %3")
2231 .arg(
PtsTime(expectedvPTS / 300),
2234 LOG(VB_GENERAL, LOG_ERR, QString(
"%1 != %2 + %3")
2238 av_packet_free(&pkt);
2239 av_packet_free(&lastRealvPkt);
2247 for (
auto *curFrame : qAsConst(Lreorder))
2261 int count = Lreorder.count();
2266 av_packet_free(&pkt);
2267 av_packet_free(&lastRealvPkt);
2274 int64_t tmp_origvPTS = origvPTS;
2278 (frame_pos + count + 1) <
m_vFrame.count())
2283 for (
auto *curFrame : qAsConst(tmpReorder))
2285 int64_t tmpPTSdiscrep = 0;
2287 tmpPTSdiscrep, numframes,
false);
2295 if (tmpPTSdiscrep != AV_NOPTS_VALUE &&
2296 tmpPTSdiscrep != PTSdiscrep)
2297 PTSdiscrep = tmpPTSdiscrep;
2299 count += tmpReorder.count();
2312 for (
int curIndex = 0; curIndex < Lreorder.count(); curIndex++)
2314 MPEG2frame *curFrame = Lreorder.at(curIndex);
2317 if (
m_saveMap.begin().key() <= frame_count)
2321 LOG(VB_GENERAL, LOG_INFO,
2322 QString(
"Saving frame #%1") .arg(frame_count));
2327 av_packet_free(&pkt);
2328 av_packet_free(&lastRealvPkt);
2332 WriteFrame(QString(
"save%1.yuv").arg(frame_count),
2339 new_discard_state =
m_delMap.begin().value();
2340 LOG(VB_GENERAL, LOG_INFO,
2341 QString(
"Del map found %1 at %2 (%3)")
2342 .arg(new_discard_state) .arg(frame_count)
2346 markedFrameP = curFrame;
2348 if (!new_discard_state)
2350 cutEndPTS = markedFrameP->
m_pkt->pts;
2352 diff2x33(cutEndPTS, expectedvPTS / 300),
2364 cutState[it3.key()] = 1;
2372 (!new_discard_state &&
2377 av_packet_free(&pkt);
2378 av_packet_free(&lastRealvPkt);
2381 ptsorder_eq_dtsorder =
true;
2383 else if (!new_discard_state &&
2386 m_vFrame.move(frame_pos, frame_pos + curIndex);
2387 ptsorder_eq_dtsorder =
true;
2391 markedFrame =
m_vFrame.at(frame_pos + curIndex);
2393 if (!new_discard_state)
2404 if (!Lreorder.isEmpty())
2406 av_packet_unref(lastRealvPkt);
2407 av_packet_ref(lastRealvPkt, Lreorder.last()->m_pkt);
2412 int64_t dtsExtra = 0;
2414 for (
auto *curFrame : qAsConst(Lreorder))
2418 if (curFrame != markedFrameP)
2421 markedFrameP =
nullptr;
2424 dec2x33(&curFrame->m_pkt->pts,
2426 deltaPTS =
diff2x33(curFrame->m_pkt->pts,
2427 expectedvPTS / 300);
2429 if (deltaPTS < -2 || deltaPTS > 2)
2431 LOG(VB_PROCESS, LOG_INFO,
2432 QString(
"PTS discrepancy: %1 != %2 on "
2434 .arg(curFrame->m_pkt->pts)
2435 .arg(expectedvPTS / 300)
2446 curFrame->m_pkt->pts = expectedvPTS / 300;
2450 LOG(VB_GENERAL, LOG_NOTICE,
2451 QString(
"Need to insert %1 frames > max "
2452 "allowed: %2. Assuming bad PTS")
2455 curFrame->m_pkt->pts = expectedvPTS / 300;
2459 lastPTS = expectedvPTS;
2463 if (curFrame == markedFrameP && new_discard_state)
2469 if (ptsorder_eq_dtsorder)
2482 m_vFrame.at(frame_pos)->m_pkt->pts = lastPTS / 300;
2488 av_packet_free(&pkt);
2489 av_packet_free(&lastRealvPkt);
2493 for (
int index = frame_pos + Lreorder.count();
2494 ret && index <
m_vFrame.count(); index++, --ret)
2496 lastPTS = expectedvPTS;
2499 Lreorder.append(
m_vFrame.at(index));
2506 for (
int i = 0; i < Lreorder.count(); i++, frame_pos++)
2511 if (curFrame != markedFrame)
2515 markedFrame =
nullptr;
2519 if (curFrame ==
nullptr)
2521 curFrame->
m_pkt->dts = (expectedDTS / 300);
2524 curFrame->
m_pkt->pts = (expectedDTS / 300);
2527 ((!ptsorder_eq_dtsorder && i == 0) ? 2 :
2529 LOG(VB_FRAME, LOG_INFO,
2530 QString(
"VID: %1 #:%2 nb: %3 pts: %4 dts: %5 "
2537 QString::number(curFrame->
m_pkt->pos)));
2540 av_packet_free(&pkt);
2541 av_packet_free(&lastRealvPkt);
2545 if (curFrame == markedFrame)
2547 markedFrame =
nullptr;
2552 expectedDTS += dtsExtra;
2556 frame_pos += Lreorder.count();
2560 PTSdiscrep), lastRealvPkt);
2564 cutEndPTS = lastRealvPkt->pts;
2577 bool backwardsPTS =
false;
2579 while (!af->isEmpty())
2588 if (CC->sample_rate == 0 || !CPC || CPC->duration == 0)
2603 90000LL * (int64_t)CPC->duration / CC->sample_rate;
2606 af->first()->m_pkt) < 0)
2608 backwardsPTS =
true;
2609 af_dlta_cnt[it.key()] = 0;
2612 int64_t tmpPTS =
diff2x33(af->first()->m_pkt->pts,
2613 origaPTS[it.key()] / 300);
2615 if (tmpPTS < -incPTS)
2618 LOG(VB_PROCESS, LOG_INFO,
2619 QString(
"Aud discard: PTS %1 < %2")
2620 .arg(
PtsTime(af->first()->m_pkt->pts))
2621 .arg(
PtsTime(origaPTS[it.key()] / 300)));
2624 af_dlta_cnt[it.key()] = 0;
2630 LOG(VB_PROCESS, LOG_INFO,
2631 QString(
"Found invalid audio PTS (off by %1) at %2")
2633 PtsTime(origaPTS[it.key()] / 300)));
2634 if (backwardsPTS && tmpPTS < 90000LL)
2637 LOG(VB_PROCESS, LOG_INFO,
2638 "Fixing missing audio frames");
2639 ptsinc((uint64_t *)&origaPTS[it.key()], 300 * tmpPTS);
2640 backwardsPTS =
false;
2642 else if (tmpPTS < 90000LL * 4)
2644 if (af_dlta_cnt[it.key()] >= 20)
2650 ptsinc((uint64_t *)&origaPTS[it.key()],
2652 af_dlta_cnt[it.key()] = 0;
2655 af_dlta_cnt[it.key()]++;
2657 af->first()->m_pkt->pts = origaPTS[it.key()] / 300;
2659 else if (tmpPTS > incPTS)
2662 backwardsPTS =
false;
2663 af_dlta_cnt[it.key()] = 0;
2667 backwardsPTS =
false;
2668 af_dlta_cnt[it.key()] = 0;
2671 int64_t nextPTS =
add2x33(af->first()->m_pkt->pts,
2672 90000LL * (int64_t)CPC->duration / CC->sample_rate);
2674 if ((cutState[it.key()] == 1 &&
2675 cmp2x33(nextPTS, cutStartPTS) > 0) ||
2676 (cutState[it.key()] == 2 &&
2677 cmp2x33(af->first()->m_pkt->pts, cutEndPTS) < 0))
2680 LOG(VB_PROCESS, LOG_INFO,
2681 QString(
"Aud in cutpoint: %1 > %2 && %3 < %4")
2683 .arg(
PtsTime(af->first()->m_pkt->pts))
2687 cutState[it.key()] = 2;
2688 ptsinc((uint64_t *)&origaPTS[it.key()], incPTS * 300);
2692 int64_t deltaPTS2 = poq.
Get(it.key(), af->first()->m_pkt);
2694 if (
udiff2x33(nextPTS, deltaPTS2) * 300 > expectedDTS &&
2695 cutState[it.key()] != 1)
2698 LOG(VB_PROCESS, LOG_INFO, QString(
"Aud not ready: %1 > %2")
2700 .arg(
PtsTime(expectedDTS / 300)));
2705 if (cutState[it.key()] == 2)
2706 cutState[it.key()] = 0;
2708 ptsinc((uint64_t *)&origaPTS[it.key()], incPTS * 300);
2710 dec2x33(&af->first()->m_pkt->pts, deltaPTS2);
2713 expectedPTS[it.key()] =
udiff2x33(nextPTS, initPTS);
2714 write_audio(lApkt_tail->m_pkt, initPTS);
2716 LOG(VB_FRAME, LOG_INFO, QString(
"AUD #%1: pts: %2 pos: %3")
2718 .arg(
PtsTime(af->first()->m_pkt->pts))
2719 .arg(af->first()->m_pkt->pos));
2722 av_packet_free(&pkt);
2723 av_packet_free(&lastRealvPkt);
2736 void *errors =
nullptr;
2738 if (*(
int *)errors) {
2739 LOG(VB_GENERAL, LOG_ERR,
2740 QString(
"joined thread failed with %1 write errors")
2741 .arg(*(
int *)errors));
2745 av_packet_free(&pkt);
2746 av_packet_free(&lastRealvPkt);
2757 fprintf(
stderr,
"%s usage:\n", s);
2758 fprintf(
stderr,
"\t--infile <file> -i <file> : Input mpg file\n");
2759 fprintf(
stderr,
"\t--outfile <file> -o <file> : Output mpg file\n");
2760 fprintf(
stderr,
"\t--dbg_lvl # -d # : Debug level\n");
2761 fprintf(
stderr,
"\t--maxframes # -m # : Max frames to insert at once (default=10)\n");
2762 fprintf(
stderr,
"\t--cutlist \"start - end\" -c : Apply a cutlist. Specify on e'-c' per cut\n");
2763 fprintf(
stderr,
"\t--no3to2 -t : Remove 3:2 pullup\n");
2764 fprintf(
stderr,
"\t--fixup -f : make PTS continuous\n");
2765 fprintf(
stderr,
"\t--ostream <dvd|ps> -e : Output stream type (defaults to ps)\n");
2766 fprintf(
stderr,
"\t--showprogress -p : show progress\n");
2767 fprintf(
stderr,
"\t--help -h : This screen\n");
2771 int main(
int argc,
char **argv)
2773 QStringList cutlist;
2774 QStringList savelist;
2775 char *infile =
nullptr, *outfile =
nullptr, *format =
nullptr;
2776 int no_repeat = 0, fix_PTS = 0, max_frames = 20, otype =
REPLEX_MPEG2;
2777 bool showprogress = 0;
2778 const struct option long_options[] =
2780 {
"infile", required_argument,
nullptr,
'i'},
2781 {
"outfile", required_argument,
nullptr,
'o'},
2782 {
"format", required_argument,
nullptr,
'r'},
2783 {
"dbg_lvl", required_argument,
nullptr,
'd'},
2784 {
"cutlist", required_argument,
nullptr,
'c'},
2785 {
"saveframe", required_argument,
nullptr,
's'},
2786 {
"ostream", required_argument,
nullptr,
'e'},
2787 {
"no3to2", no_argument,
nullptr,
't'},
2788 {
"fixup", no_argument,
nullptr,
'f'},
2789 {
"showprogress", no_argument,
nullptr,
'p'},
2790 {
"help", no_argument ,
nullptr,
'h'},
2796 int option_index = 0;
2798 c = getopt_long (argc, argv,
"i:o:d:r:m:c:s:e:tfph",
2799 long_options, &option_index);
2820 if (strlen(optarg) == 3 && strncmp(optarg,
"dvd", 3) == 0)
2829 max_frames = atoi(optarg);
2833 cutlist.append(optarg);
2844 savelist.append(optarg);
2848 showprogress =
true;
2860 if (infile ==
nullptr || outfile ==
nullptr)
2863 MPEG2fixup m2f(infile, outfile,
nullptr, format,
2864 no_repeat, fix_PTS, max_frames,
2865 showprogress, otype);
2867 if (cutlist.count())
2869 if (savelist.count())
2879 LOG(VB_GENERAL, LOG_INFO,
"Generating Keyframe Index");
2890 LOG(VB_GENERAL, LOG_INFO,
"Seek tables are not required for MKV");
2894 AVPacket *pkt = av_packet_alloc();
2897 LOG(VB_GENERAL, LOG_ERR,
"packet allocation failed");
2901 uint64_t totalDuration = 0;
2902 while (av_read_frame(
m_inputFC, pkt) >= 0)
2904 if (pkt->stream_index ==
m_vidId)
2906 if (pkt->flags & AV_PKT_FLAG_KEY)
2908 posMap[count] = pkt->pos;
2909 durMap[count] = totalDuration;
2918 av_q2d(
m_inputFC->streams[pkt->stream_index]->time_base) *
2919 pkt->duration * 1000;
2922 av_packet_unref(pkt);
2926 av_packet_free(&pkt);
2930 LOG(VB_GENERAL, LOG_NOTICE,
"Transcode Completed");