From a5576e56f060f224b63f8bfe1bc12ff95ff210b7 Mon Sep 17 00:00:00 2001
From: Gavin Hurlbut <ghurlbut@mythtv.org>
Date: Sun, 23 Sep 2012 19:09:07 -0700
Subject: [PATCH] Fix video encode in MPEG2 "lossless" transcoding
Fixes #11118
It seems that the new video encode API call pipelines the encoding, returning
after each input frame, but not returning a packet the first time around in all
cases. This change makes it encode the packet, and then keep calling the API
until a packet has actually been encoded (flushing the output).
---
mythtv/programs/mythtranscode/mpeg2fix.cpp | 39 +++++++++++++++------------
mythtv/programs/mythtranscode/mpeg2fix.h | 2 +-
2 files changed, 23 insertions(+), 18 deletions(-)
diff --git a/mythtv/programs/mythtranscode/mpeg2fix.cpp b/mythtv/programs/mythtranscode/mpeg2fix.cpp
index 0550e0b..23184f1 100644
|
a
|
b
|
extern "C" {
|
| 1063 | 1063 | #include "helper.h" |
| 1064 | 1064 | } |
| 1065 | 1065 | |
| 1066 | | int MPEG2fixup::BuildFrame(AVPacket *pkt, QString fname) |
| | 1066 | bool MPEG2fixup::BuildFrame(AVPacket *pkt, QString fname) |
| 1067 | 1067 | { |
| 1068 | 1068 | const mpeg2_info_t *info; |
| 1069 | 1069 | int outbuf_size; |
| … |
… |
int MPEG2fixup::BuildFrame(AVPacket *pkt, QString fname)
|
| 1074 | 1074 | |
| 1075 | 1075 | info = mpeg2_info(img_decoder); |
| 1076 | 1076 | if (!info->display_fbuf) |
| 1077 | | return 1; |
| | 1077 | return true; |
| 1078 | 1078 | |
| 1079 | 1079 | outbuf_size = info->sequence->width * info->sequence->height * 2; |
| 1080 | 1080 | |
| … |
… |
int MPEG2fixup::BuildFrame(AVPacket *pkt, QString fname)
|
| 1116 | 1116 | { |
| 1117 | 1117 | free(picture); |
| 1118 | 1118 | LOG(VB_GENERAL, LOG_ERR, "Couldn't find MPEG2 encoder"); |
| 1119 | | return 1; |
| | 1119 | return true; |
| 1120 | 1120 | } |
| 1121 | 1121 | |
| 1122 | 1122 | c = avcodec_alloc_context3(NULL); |
| 1123 | 1123 | |
| 1124 | | //We disable all optimizations for the time being. There shouldn't be too |
| 1125 | | //much encoding going on, and the optimizations have been shown to cause |
| 1126 | | //corruption in some cases |
| 1127 | | c->dsp_mask = 0xffff; |
| 1128 | | |
| 1129 | 1124 | //NOTE: The following may seem wrong, but avcodec requires |
| 1130 | 1125 | //sequence->progressive == frame->progressive |
| 1131 | 1126 | //We fix the discrepancy by discarding avcodec's sequence header, and |
| … |
… |
int MPEG2fixup::BuildFrame(AVPacket *pkt, QString fname)
|
| 1164 | 1159 | { |
| 1165 | 1160 | free(picture); |
| 1166 | 1161 | LOG(VB_GENERAL, LOG_ERR, "could not open codec"); |
| 1167 | | return 1; |
| | 1162 | return true; |
| 1168 | 1163 | } |
| 1169 | 1164 | |
| 1170 | 1165 | int got_packet = 0; |
| | 1166 | int ret; |
| | 1167 | bool initial = true; |
| 1171 | 1168 | |
| 1172 | | int ret = avcodec_encode_video2(c, pkt, picture, &got_packet); |
| 1173 | | |
| 1174 | | if (ret < 0 || !got_packet) |
| | 1169 | // Need to call this repeatedly as it seems to be pipelined. The first |
| | 1170 | // call will return no packet, then the second one will flush it. In case |
| | 1171 | // it becomes more pipelined, just loop until it creates a packet or errors |
| | 1172 | // out. |
| | 1173 | while (!got_packet) |
| 1175 | 1174 | { |
| 1176 | | free(picture); |
| 1177 | | LOG(VB_GENERAL, LOG_ERR, |
| 1178 | | QString("avcodec_encode_video failed (%1)").arg(pkt->size)); |
| 1179 | | return 1; |
| | 1175 | ret = avcodec_encode_video2(c, pkt, (initial ? picture : NULL), |
| | 1176 | &got_packet); |
| | 1177 | |
| | 1178 | if (ret < 0) |
| | 1179 | { |
| | 1180 | free(picture); |
| | 1181 | LOG(VB_GENERAL, LOG_ERR, |
| | 1182 | QString("avcodec_encode_video2 failed (%1)").arg(ret)); |
| | 1183 | return true; |
| | 1184 | } |
| 1180 | 1185 | } |
| 1181 | 1186 | |
| 1182 | 1187 | if (!fname.isEmpty()) |
| … |
… |
int MPEG2fixup::BuildFrame(AVPacket *pkt, QString fname)
|
| 1198 | 1203 | av_freep(&c); |
| 1199 | 1204 | av_freep(&picture); |
| 1200 | 1205 | |
| 1201 | | return 0; |
| | 1206 | return false; |
| 1202 | 1207 | } |
| 1203 | 1208 | |
| 1204 | 1209 | #define MAX_FRAMES 20000 |
diff --git a/mythtv/programs/mythtranscode/mpeg2fix.h b/mythtv/programs/mythtranscode/mpeg2fix.h
index 96ecbbb..fe74ac0 100644
|
a
|
b
|
class MPEG2fixup
|
| 171 | 171 | void WriteFrame(QString filename, AVPacket *pkt); |
| 172 | 172 | void WriteYUV(QString filename, const mpeg2_info_t *info); |
| 173 | 173 | void WriteData(QString filename, uint8_t *data, int size); |
| 174 | | int BuildFrame(AVPacket *pkt, QString fname); |
| | 174 | bool BuildFrame(AVPacket *pkt, QString fname); |
| 175 | 175 | MPEG2frame *GetPoolFrame(AVPacket *pkt); |
| 176 | 176 | MPEG2frame *GetPoolFrame(MPEG2frame *f); |
| 177 | 177 | int GetFrame(AVPacket *pkt); |