mirror of
https://github.com/tuxbox-neutrino/libstb-hal.git
synced 2025-08-26 23:13:16 +02:00
raspi/AVDec: various improvements for A/V decoders
* retry on errors in the decoding loop * better interaction with avcodec_omx
This commit is contained in:
@@ -191,6 +191,7 @@ AVDec::AVDec()
|
|||||||
AVDec::~AVDec()
|
AVDec::~AVDec()
|
||||||
{
|
{
|
||||||
stop_video();
|
stop_video();
|
||||||
|
stop_audio();
|
||||||
|
|
||||||
if (OMX_Deinit() != OMX_ErrorNone) /* TODO: what now? */
|
if (OMX_Deinit() != OMX_ErrorNone) /* TODO: what now? */
|
||||||
lt_info("AVDec::~AVDec: OMX_Deinit() failed!\n");
|
lt_info("AVDec::~AVDec: OMX_Deinit() failed!\n");
|
||||||
@@ -287,7 +288,7 @@ void aDec::run()
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
codec_new_channel(&codecs.acodec);
|
codec_new_channel(&codecs.acodec);
|
||||||
codecs.acodec.first_packet = 1;
|
codecs.acodec.first_packet = 1;
|
||||||
codecs.acodec.is_running = 1;
|
codecs.acodec.is_running = 0;
|
||||||
struct packet_t *packet;
|
struct packet_t *packet;
|
||||||
/* libavcodec & friends */
|
/* libavcodec & friends */
|
||||||
AVCodec *codec;
|
AVCodec *codec;
|
||||||
@@ -295,11 +296,15 @@ void aDec::run()
|
|||||||
AVCodecContext *c = NULL;
|
AVCodecContext *c = NULL;
|
||||||
AVInputFormat *inp;
|
AVInputFormat *inp;
|
||||||
AVFrame *frame;
|
AVFrame *frame;
|
||||||
uint8_t *inbuf = (uint8_t *)av_malloc(AINBUF_SIZE);
|
uint8_t *inbuf;
|
||||||
AVPacket avpkt;
|
AVPacket avpkt;
|
||||||
char tmp[128] = "unknown";
|
char tmp[128] = "unknown";
|
||||||
|
|
||||||
curr_pts = 0;
|
curr_pts = 0;
|
||||||
|
bool retry;
|
||||||
|
again:
|
||||||
|
inbuf = (uint8_t *)av_malloc(AINBUF_SIZE);
|
||||||
|
retry = false;
|
||||||
av_init_packet(&avpkt);
|
av_init_packet(&avpkt);
|
||||||
inp = av_find_input_format("mpegts");
|
inp = av_find_input_format("mpegts");
|
||||||
helper_struct h;
|
helper_struct h;
|
||||||
@@ -353,10 +358,13 @@ void aDec::run()
|
|||||||
int gotframe = 0;
|
int gotframe = 0;
|
||||||
if (av_read_frame(avfc, &avpkt) < 0) {
|
if (av_read_frame(avfc, &avpkt) < 0) {
|
||||||
lt_info("aDec: av_read_frame < 0\n");
|
lt_info("aDec: av_read_frame < 0\n");
|
||||||
usleep(1000);
|
retry = true;
|
||||||
continue;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (codec_is_running(&codecs.acodec) != 1) {
|
||||||
|
av_free_packet(&avpkt);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
int len = avcodec_decode_audio4(c, frame, &gotframe, &avpkt);
|
int len = avcodec_decode_audio4(c, frame, &gotframe, &avpkt);
|
||||||
if (gotframe && dec_running) {
|
if (gotframe && dec_running) {
|
||||||
curr_pts = (avpkt.pts);
|
curr_pts = (avpkt.pts);
|
||||||
@@ -374,7 +382,7 @@ void aDec::run()
|
|||||||
codec_queue_add_item(&codecs.acodec, packet, MSG_PACKET);
|
codec_queue_add_item(&codecs.acodec, packet, MSG_PACKET);
|
||||||
}
|
}
|
||||||
if (len != avpkt.size)
|
if (len != avpkt.size)
|
||||||
lt_info("aDec: decoded len: %d pkt.size: %d\n", len, avpkt.size);
|
lt_info("aDec: decoded len: %d pkt.size: %d gotframe %d\n", len, avpkt.size, gotframe);
|
||||||
av_free_packet(&avpkt);
|
av_free_packet(&avpkt);
|
||||||
}
|
}
|
||||||
lt_info("aDec: decoder loop exited\n");
|
lt_info("aDec: decoder loop exited\n");
|
||||||
@@ -391,6 +399,8 @@ void aDec::run()
|
|||||||
avformat_close_input(&avfc);
|
avformat_close_input(&avfc);
|
||||||
av_free(pIOCtx->buffer);
|
av_free(pIOCtx->buffer);
|
||||||
av_free(pIOCtx);
|
av_free(pIOCtx);
|
||||||
|
if (retry && dec_running)
|
||||||
|
goto again;
|
||||||
lt_info("======================== end audio decoder thread ================================\n");
|
lt_info("======================== end audio decoder thread ================================\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,16 +426,21 @@ void vDec::run()
|
|||||||
|
|
||||||
AVFormatContext *avfc = NULL;
|
AVFormatContext *avfc = NULL;
|
||||||
AVInputFormat *inp;
|
AVInputFormat *inp;
|
||||||
uint8_t *inbuf = (uint8_t *)av_malloc(VINBUF_SIZE);
|
uint8_t *inbuf;
|
||||||
AVPacket avpkt;
|
AVPacket avpkt;
|
||||||
struct packet_t *packet;
|
struct packet_t *packet;
|
||||||
|
|
||||||
|
bool retry;
|
||||||
|
again:
|
||||||
|
retry = false;
|
||||||
av_init_packet(&avpkt);
|
av_init_packet(&avpkt);
|
||||||
inp = av_find_input_format("mpegts");
|
|
||||||
helper_struct h;
|
helper_struct h;
|
||||||
h.d = this;
|
h.d = this;
|
||||||
h.audio = false;
|
h.audio = false;
|
||||||
dec_running = true;
|
dec_running = true;
|
||||||
|
retry_open:
|
||||||
|
inbuf = (uint8_t *)av_malloc(VINBUF_SIZE);
|
||||||
|
inp = av_find_input_format("mpegts");
|
||||||
AVIOContext *pIOCtx = avio_alloc_context(inbuf, VINBUF_SIZE, // internal Buffer and its size
|
AVIOContext *pIOCtx = avio_alloc_context(inbuf, VINBUF_SIZE, // internal Buffer and its size
|
||||||
0, // bWriteable (1=true,0=false)
|
0, // bWriteable (1=true,0=false)
|
||||||
&h, // user data; will be passed to our callback functions
|
&h, // user data; will be passed to our callback functions
|
||||||
@@ -435,12 +450,15 @@ void vDec::run()
|
|||||||
avfc = avformat_alloc_context();
|
avfc = avformat_alloc_context();
|
||||||
avfc->pb = pIOCtx;
|
avfc->pb = pIOCtx;
|
||||||
avfc->iformat = inp;
|
avfc->iformat = inp;
|
||||||
avfc->probesize = 188*1000;
|
avfc->probesize = 188 * 100;
|
||||||
|
|
||||||
if ((ret = avformat_open_input(&avfc, NULL, inp, NULL)) < 0) {
|
if ((ret = avformat_open_input(&avfc, NULL, inp, NULL)) < 0) {
|
||||||
lt_info("vDec: Could not open input: %d ctx:%p\n", ret, avfc);
|
lt_info("vDec: Could not open input: %d ctx:%p\n", ret, avfc);
|
||||||
|
if (dec_running)
|
||||||
|
goto retry_open;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
while (avfc->nb_streams < 1)
|
while (avfc->nb_streams < 1)
|
||||||
{
|
{
|
||||||
lt_info("vDec: nb_streams %d, should be 1 => retry\n", avfc->nb_streams);
|
lt_info("vDec: nb_streams %d, should be 1 => retry\n", avfc->nb_streams);
|
||||||
@@ -455,12 +473,12 @@ void vDec::run()
|
|||||||
if (avfc->streams[0]->codec->codec_type != AVMEDIA_TYPE_VIDEO)
|
if (avfc->streams[0]->codec->codec_type != AVMEDIA_TYPE_VIDEO)
|
||||||
lt_info("vDec: no video codec? 0x%x streams: %d\n",
|
lt_info("vDec: no video codec? 0x%x streams: %d\n",
|
||||||
avfc->streams[0]->codec->codec_type, avfc->nb_streams);
|
avfc->streams[0]->codec->codec_type, avfc->nb_streams);
|
||||||
|
#endif
|
||||||
lt_info("vDec: decoder loop starts\n");
|
lt_info("vDec: decoder loop starts\n");
|
||||||
while (dec_running) {
|
while (dec_running) {
|
||||||
if (av_read_frame(avfc, &avpkt) < 0) {
|
if (av_read_frame(avfc, &avpkt) < 0) {
|
||||||
usleep(1000);
|
lt_info("vDec: av_read_frame < 0\n");
|
||||||
continue;
|
retry = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (dec_running) {
|
if (dec_running) {
|
||||||
@@ -468,7 +486,7 @@ void vDec::run()
|
|||||||
lt_debug("vDec: pts 0x%" PRIx64 " %3f\n", vpts, vpts/90000.0);
|
lt_debug("vDec: pts 0x%" PRIx64 " %3f\n", vpts, vpts/90000.0);
|
||||||
packet = (packet_t *)malloc(sizeof(*packet));
|
packet = (packet_t *)malloc(sizeof(*packet));
|
||||||
packet->PTS = av_rescale_q(avpkt.pts, avfc->streams[0]->time_base, omx_timebase);
|
packet->PTS = av_rescale_q(avpkt.pts, avfc->streams[0]->time_base, omx_timebase);
|
||||||
packet->DTS = -1;
|
packet->DTS = av_rescale_q(avpkt.dts, avfc->streams[0]->time_base, omx_timebase);
|
||||||
packet->packetlength = avpkt.size;
|
packet->packetlength = avpkt.size;
|
||||||
packet->packet = (uint8_t *)malloc(avpkt.size);
|
packet->packet = (uint8_t *)malloc(avpkt.size);
|
||||||
memcpy(packet->packet, avpkt.data, avpkt.size);
|
memcpy(packet->packet, avpkt.data, avpkt.size);
|
||||||
@@ -483,7 +501,8 @@ void vDec::run()
|
|||||||
avformat_close_input(&avfc);
|
avformat_close_input(&avfc);
|
||||||
av_free(pIOCtx->buffer);
|
av_free(pIOCtx->buffer);
|
||||||
av_free(pIOCtx);
|
av_free(pIOCtx);
|
||||||
|
if (retry && dec_running)
|
||||||
|
goto again;
|
||||||
lt_info("======================== end video decoder thread ================================\n");
|
lt_info("======================== end video decoder thread ================================\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user