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:
Stefan Seyfried
2013-10-20 01:11:36 +02:00
parent 2784941b7e
commit 2f7cb6401f

View File

@@ -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");
} }