mirror of
https://github.com/owntone/owntone-server.git
synced 2025-01-14 16:25:03 -05:00
[transcode] Don't pass error to player on eof + some comments and cleaning
This commit is contained in:
parent
e20d2c544d
commit
3e80e5c517
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user