[transcode] Don't pass error to player on eof + some comments and cleaning

This commit is contained in:
ejurgensen 2015-10-22 22:09:19 +02:00
parent e20d2c544d
commit 3e80e5c517
4 changed files with 61 additions and 33 deletions

View File

@ -215,7 +215,7 @@ stream_chunk_xcode_cb(int fd, short event, void *arg)
st = (struct stream_ctx *)arg; st = (struct stream_ctx *)arg;
xcoded = transcode(st->xcode, st->evbuf, STREAM_CHUNK_SIZE, &dummy); xcoded = transcode(st->evbuf, STREAM_CHUNK_SIZE, st->xcode, &dummy);
if (xcoded <= 0) if (xcoded <= 0)
{ {
if (xcoded == 0) if (xcoded == 0)

View File

@ -960,14 +960,14 @@ stream_read(struct player_source *ps, int len)
switch (ps->data_kind) switch (ps->data_kind)
{ {
case DATA_KIND_HTTP: case DATA_KIND_HTTP:
ret = transcode(ps->xcode, audio_buf, len, &icy_timer); ret = transcode(audio_buf, len, ps->xcode, &icy_timer);
if (icy_timer) if (icy_timer)
metadata_check_icy(); metadata_check_icy();
break; break;
case DATA_KIND_FILE: case DATA_KIND_FILE:
ret = transcode(ps->xcode, audio_buf, len, &icy_timer); ret = transcode(audio_buf, len, ps->xcode, &icy_timer);
break; break;
#ifdef HAVE_SPOTIFY_H #ifdef HAVE_SPOTIFY_H

View File

@ -261,7 +261,7 @@ decode_stream(struct decode_ctx *ctx, AVStream *in_stream)
* @out stream_index * @out stream_index
* Set to the input stream index corresponding to the packet * Set to the input stream index corresponding to the packet
* @in ctx Decode context * @in ctx Decode context
* @return 0 on success, -1 on failure (including eof) * @return 0 if OK, < 0 on error or end of file
*/ */
static int static int
read_packet(AVPacket *packet, AVStream **stream, unsigned int *stream_index, struct decode_ctx *ctx) read_packet(AVPacket *packet, AVStream **stream, unsigned int *stream_index, struct decode_ctx *ctx)
@ -295,7 +295,7 @@ read_packet(AVPacket *packet, AVStream **stream, unsigned int *stream_index, str
av_strerror(ret, errmsg, 128); av_strerror(ret, errmsg, 128);
DPRINTF(E_WARN, L_XCODE, "Could not read frame: %s\n", errmsg); DPRINTF(E_WARN, L_XCODE, "Could not read frame: %s\n", errmsg);
free(errmsg); free(errmsg);
return -1; return ret;
} }
*packet = ctx->packet; *packet = ctx->packet;
@ -1439,10 +1439,10 @@ transcode_decoded_free(struct decoded_frame *decoded)
/* Encoding, decoding and transcoding */ /* Encoding, decoding and transcoding */
struct decoded_frame *
transcode_decode(struct decode_ctx *ctx) int
transcode_decode(struct decoded_frame **decoded, struct decode_ctx *ctx)
{ {
struct decoded_frame *decoded;
AVPacket packet; AVPacket packet;
AVStream *in_stream; AVStream *in_stream;
AVFrame *frame; AVFrame *frame;
@ -1457,7 +1457,8 @@ transcode_decode(struct decode_ctx *ctx)
if (!frame) if (!frame)
{ {
DPRINTF(E_LOG, L_XCODE, "Out of memory for decode frame\n"); DPRINTF(E_LOG, L_XCODE, "Out of memory for decode frame\n");
return NULL;
return -1;
} }
// Loop until we either fail or get a frame // Loop until we either fail or get a frame
@ -1471,11 +1472,16 @@ transcode_decode(struct decode_ctx *ctx)
// with empty input until no more frames are returned // with empty input until no more frames are returned
DPRINTF(E_DBG, L_XCODE, "Could not read packet (eof?), will flush decoders\n"); DPRINTF(E_DBG, L_XCODE, "Could not read packet (eof?), will flush decoders\n");
used = 1;
got_frame = flush_decoder(frame, &in_stream, &stream_index, ctx); got_frame = flush_decoder(frame, &in_stream, &stream_index, ctx);
if (got_frame) if (got_frame)
break; break;
av_frame_free(&frame);
if (ret == AVERROR_EOF)
return 0;
else else
goto out_error; return -1;
} }
// "used" will tell us how much of the packet was decoded. We may // "used" will tell us how much of the packet was decoded. We may
@ -1490,13 +1496,16 @@ transcode_decode(struct decode_ctx *ctx)
// so let's try MAX_BAD_PACKETS times before giving up // so let's try MAX_BAD_PACKETS times before giving up
if (used < 0) if (used < 0)
{ {
DPRINTF(E_WARN, L_XCODE, "Couldn't decode packet\n"); DPRINTF(E_DBG, L_XCODE, "Couldn't decode packet\n");
retry += 1; retry += 1;
if (retry < MAX_BAD_PACKETS) if (retry < MAX_BAD_PACKETS)
continue; continue;
else
goto out_error; DPRINTF(E_LOG, L_XCODE, "Couldn't decode packet after %i retries\n", MAX_BAD_PACKETS);
av_frame_free(&frame);
return -1;
} }
// decoder didn't process the entire packet, so flag a resume, meaning // decoder didn't process the entire packet, so flag a resume, meaning
@ -1515,24 +1524,19 @@ transcode_decode(struct decode_ctx *ctx)
// Return the decoded frame and stream index // Return the decoded frame and stream index
frame->pts = av_frame_get_best_effort_timestamp(frame); frame->pts = av_frame_get_best_effort_timestamp(frame);
decoded = malloc(sizeof(struct decoded_frame)); *decoded = malloc(sizeof(struct decoded_frame));
if (!decoded) if (!*decoded)
{ {
DPRINTF(E_LOG, L_XCODE, "Out of memory for decoded result\n"); DPRINTF(E_LOG, L_XCODE, "Out of memory for decoded result\n");
goto out_error;
av_frame_free(&frame);
return -1;
} }
decoded->frame = frame; (*decoded)->frame = frame;
decoded->stream_index = stream_index; (*decoded)->stream_index = stream_index;
return decoded; return used;
out_error:
DPRINTF(E_DBG, L_XCODE, "Decode failure - probably EOF\n");
av_frame_free(&frame);
return NULL;
} }
// Filters and encodes // Filters and encodes
@ -1574,7 +1578,7 @@ transcode_encode(struct evbuffer *evbuf, struct decoded_frame *decoded, struct e
} }
int int
transcode(struct transcode_ctx *ctx, struct evbuffer *evbuf, int wanted, int *icy_timer) transcode(struct evbuffer *evbuf, int wanted, struct transcode_ctx *ctx, int *icy_timer)
{ {
struct decoded_frame *decoded; struct decoded_frame *decoded;
int processed; int processed;
@ -1583,9 +1587,9 @@ transcode(struct transcode_ctx *ctx, struct evbuffer *evbuf, int wanted, int *ic
processed = 0; processed = 0;
while (processed < wanted) while (processed < wanted)
{ {
decoded = transcode_decode(ctx->decode_ctx); ret = transcode_decode(&decoded, ctx->decode_ctx);
if (!decoded) if (ret <= 0)
return -1; return ret;
ret = transcode_encode(evbuf, decoded, ctx->encode_ctx); ret = transcode_encode(evbuf, decoded, ctx->encode_ctx);
transcode_decoded_free(decoded); transcode_decoded_free(decoded);

View File

@ -56,14 +56,38 @@ void
transcode_decoded_free(struct decoded_frame *decoded); transcode_decoded_free(struct decoded_frame *decoded);
// Transcoding // Transcoding
struct decoded_frame *
transcode_decode(struct decode_ctx *ctx);
/* Demuxes and decodes the next packet from the input.
*
* @out decoded A newly allocated struct with a pointer to the frame and the
* stream. Must be freed with transcode_decoded_free().
* @in ctx Decode context
* @return Bytes read if OK, negative if error, 0 if EOF
*/
int
transcode_decode(struct decoded_frame **decoded, struct decode_ctx *ctx);
/* Encodes and remuxes a frame. Also resamples if needed.
*
* @out evbuf An evbuffer filled with remuxed data
* @in frame The frame to encode, e.g. from transcode_decode
* @in wanted Bytes that the caller wants processed
* @in ctx Encode context
* @return Length of evbuf if OK, negative if error
*/
int int
transcode_encode(struct evbuffer *evbuf, struct decoded_frame *decoded, struct encode_ctx *ctx); transcode_encode(struct evbuffer *evbuf, struct decoded_frame *decoded, struct encode_ctx *ctx);
/* Demuxes, decodes, encodes and remuxes the next packet from the input.
*
* @out evbuf An evbuffer filled with remuxed data
* @in wanted Bytes that the caller wants processed
* @in ctx Transcode context
* @out icy_timer True if METADATA_ICY_INTERVAL has elapsed
* @return Bytes processed if OK, negative if error, 0 if EOF
*/
int int
transcode(struct transcode_ctx *ctx, struct evbuffer *evbuf, int wanted, int *icy_timer); transcode(struct evbuffer *evbuf, int wanted, struct transcode_ctx *ctx, int *icy_timer);
struct decoded_frame * struct decoded_frame *
transcode_raw2frame(uint8_t *data, size_t size); transcode_raw2frame(uint8_t *data, size_t size);