diff options
| -rw-r--r-- | src/cache/entry.h | 2 | ||||
| -rw-r--r-- | src/codec/codec.h | 21 | ||||
| -rw-r--r-- | src/codec/ffmpeg/decoder.c | 34 | ||||
| -rw-r--r-- | src/codec/ffmpeg/demuxer.c | 13 | ||||
| -rw-r--r-- | src/codec/ffmpeg/resampler.c | 3 | ||||
| -rw-r--r-- | src/fruits/cmsrv/ui.c | 2 | ||||
| -rw-r--r-- | src/server/server.c | 4 | ||||
| -rw-r--r-- | tests/cue_splitter.c | 7 |
8 files changed, 48 insertions, 38 deletions
diff --git a/src/cache/entry.h b/src/cache/entry.h index 693e68b..ef2ee41 100644 --- a/src/cache/entry.h +++ b/src/cache/entry.h @@ -17,6 +17,7 @@ - cue + multiple files - dvd/bluray (drive or iso) - live source (radio antenna) + - remote resource Chapters: - Potential resources with chapters: @@ -67,6 +68,7 @@ and loaded with different cds. [ ] Separate cch_handler from cch_entry. - Move waits to entry? + - Pick first entry in order as the unloaded entry, remove every other entry. - Create cache entry with argument like file, cue, http, hls, etc. - Handlers created internally, and run on different step. [ ] Maybe rename cch_handler. diff --git a/src/codec/codec.h b/src/codec/codec.h index 9820316..0829847 100644 --- a/src/codec/codec.h +++ b/src/codec/codec.h @@ -425,18 +425,28 @@ static inline s32 camu_pixel_format_from_channels(s32 channels) static inline void camu_codec_frame_discard(struct camu_codec_frame *frame) { + switch (frame->mode) { #ifdef CAMU_HAVE_FFMPEG - if (frame->mode == CAMU_FFMPEG_COMPAT) av_frame_free(&frame->av.frame); + case CAMU_FFMPEG_COMPAT: + av_frame_free(&frame->av.frame); + break; #endif - if (frame->mode == CAMU_NORMAL && frame->data) al_free(frame->data); + case CAMU_NORMAL: + if (frame->data) al_free(frame->data); + break; + } al_free(frame); } static inline s32 camu_guess_format(str *short_name, str *ext, str *mime_type) { - if (al_str_eq(ext, &al_str_c(".png"))) { + if ((ext && al_str_eq(ext, &al_str_c(".png"))) || + (short_name && al_str_eq(short_name, &al_str_c("png"))) || + (mime_type && al_str_eq(mime_type, &al_str_c("image/png")))) { return CAMU_CODEC_PNG; - } else if (al_str_eq(ext, &al_str_c(".jpeg")) || al_str_eq(ext, &al_str_c(".jpg"))) { + } else if ((ext && (al_str_eq(ext, &al_str_c(".jpeg")) || al_str_eq(ext, &al_str_c(".jpg")))) || + (short_name && al_str_eq(short_name, &al_str_c("jpeg"))) || + (mime_type && al_str_eq(mime_type, &al_str_c("image/jpeg")))) { return CAMU_CODEC_JPEG; } #ifdef CAMU_HAVE_FFMPEG @@ -450,9 +460,6 @@ static inline s32 camu_guess_format(str *short_name, str *ext, str *mime_type) if (c_mime_type) al_free(c_mime_type); // In FFmpeg AV_CODEC_ID_MJPEG also means "image2". if (fmt) return (fmt->audio_codec != AV_CODEC_ID_NONE) ? fmt->audio_codec : fmt->video_codec; -#else - (void)short_name; - (void)mime_type; #endif return -1; } diff --git a/src/codec/ffmpeg/decoder.c b/src/codec/ffmpeg/decoder.c index 47bab44..6eff28b 100644 --- a/src/codec/ffmpeg/decoder.c +++ b/src/codec/ffmpeg/decoder.c @@ -60,6 +60,7 @@ static s32 get_buffer2(AVCodecContext *context, AVFrame *pic, s32 flags) return ret; } +// This is currently untested. static s32 init_hwframe_context(struct camu_ff_decoder *av, AVCodecContext *context, AVBufferRef *hw_device_context) { AVBufferRef *hw_frames_ref; @@ -83,9 +84,11 @@ static s32 init_hwframe_context(struct camu_ff_decoder *av, AVCodecContext *cont return ret; } + context->hw_frames_ctx = hw_frames_ref; + /* context->hw_frames_ctx = av_buffer_ref(hw_frames_ref); - av_buffer_unref(&hw_frames_ref); + */ return ret; } @@ -128,8 +131,6 @@ out: static s32 init_hwdevice_context(struct camu_ff_decoder *av, AVCodecContext *context) { - av->hw_context = NULL; - s32 ret = av_hwdevice_ctx_create(&av->hw_context, av->hw_device_type, NULL, NULL, 0); if (ret < 0) { log_error("Failed to create specified HW device."); @@ -208,12 +209,14 @@ static void close_internal(struct camu_ff_decoder *av) { if (av->codec_context) avcodec_free_context(&av->codec_context); #ifdef CAMU_FF_DECODER_HWACCEL - if (av->errored_hw_context) avcodec_free_context(&av->errored_hw_context); + if (av->hw_context) av_buffer_unref(&av->hw_context); al_array_free(av->supported_hw_codecs); al_array_free(av->supported_hw_devices); + if (av->errored_hw_context) avcodec_free_context(&av->errored_hw_context); #endif } +// If decoder_init() fails, we should still expect decoder_free() to by called which will run close_internal(). static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *renderer, struct camu_codec_stream *stream, void (*callback)(void *, struct camu_codec_frame *), void *userdata) { @@ -221,16 +224,17 @@ static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *rend av->codec_context = NULL; #ifdef CAMU_FF_DECODER_HWACCEL - av->errored_hw_context = NULL; + av->hw_context = NULL; al_array_init(av->supported_hw_codecs); al_array_init(av->supported_hw_devices); + av->errored_hw_context = NULL; #endif AVCodecParameters *codecpar = stream->av.stream->codecpar; const AVCodec *codec = avcodec_find_decoder(codecpar->codec_id); if (!codec) { log_error("Failed to find decoder."); - goto err; + return false; } bool is_video = codecpar->codec_type == AVMEDIA_TYPE_VIDEO && stream->duration > 0; @@ -253,6 +257,7 @@ static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *rend const AVCodec *hw_codec; al_array_foreach(av->supported_hw_codecs, i, hw_codec) { if (hw_codec->id == codecpar->codec_id) { + // @TODO: hw_codec's without a hwdevice (v4l2m2m, cuvid, amf). size_t length = al_strlen(hw_codec->wrapper_name); av->hw_device_type = hw_device_supported_by_name(av, hw_codec->wrapper_name, length); if (get_hwdevice_config(av, hw_codec, av->hw_device_type)) { @@ -270,7 +275,7 @@ static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *rend #endif if (!alloc_codec_context_internal(av, codec, codecpar)) { - goto err; + return false; } #ifdef CAMU_FF_DECODER_HWACCEL @@ -295,9 +300,10 @@ static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *rend if (av->hw_device_type == AV_HWDEVICE_TYPE_NONE) { #endif // FF_THREAD_FRAME or FF_THREAD_SLICE. - // Both modes can get choked on certain videos, sometimes SLICE can squeeze - // out a little more performance but a higher thread_count with FRAME seems - // like the safest default. + // Both modes can get choked on certain videos, higher thread_count with + // FRAME seems like the safest default. + // @TODO: Check ffmpeg source, SLICE + FRAME? + // - https://ffmpeg.org/ffmpeg-codecs.html#Codec-Options av->codec_context->thread_type = FF_THREAD_FRAME; av->codec_context->thread_count = av->thread_count; log_info("Using %i threads for decoder.", av->thread_count); @@ -310,7 +316,7 @@ static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *rend //av->codec_context->flags2 |= AV_CODEC_FLAG2_FAST; if (!open_avcodec_internal(av, codec)) { - goto err; + return false; } log_info("Codec: %s (%s) %lldkbps.", codec->name, @@ -321,15 +327,12 @@ static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *rend av->userdata = userdata; return true; -err: - close_internal(av); - return false; } static s32 send_packet(struct camu_ff_decoder *av, AVPacket *pkt) { s32 ret = avcodec_send_packet(av->codec_context, pkt); - if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) { + if (ret < 0 && !(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)) { log_error("Error sending packet to the decoder (%s).", av_err2str(ret)); } return ret; @@ -361,6 +364,7 @@ static s32 receive_frames(struct camu_ff_decoder *av) al_free(frame); // Checking for EAGAIN should prevent an infinite loop. if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) break; + log_error("Error receiving packet from the decoder (%s).", av_err2str(ret)); continue; } if (avframe->best_effort_timestamp == AV_NOPTS_VALUE) { diff --git a/src/codec/ffmpeg/demuxer.c b/src/codec/ffmpeg/demuxer.c index a8f1df7..e5aa2f6 100644 --- a/src/codec/ffmpeg/demuxer.c +++ b/src/codec/ffmpeg/demuxer.c @@ -31,7 +31,7 @@ static bool ff_demuxer_init(struct camu_demuxer *demux, struct cch_handle *handl av->format_context = avformat_alloc_context(); if (!av->format_context) { log_error("Failed to create format context."); - goto err; + return false; } // This is meant to be the "block size" so, if I understand correctly, that would mean @@ -40,7 +40,7 @@ static bool ff_demuxer_init(struct camu_demuxer *demux, struct cch_handle *handl av->io_context = avio_alloc_context(buf, al_page_size, 0, handle, camu_avio_read, NULL, camu_avio_seek); if (!av->io_context) { log_error("Failed to create custom io context."); - goto err; + return false; } if (!cch_handle_can_seek(handle)) { @@ -67,7 +67,7 @@ static bool ff_demuxer_init(struct camu_demuxer *demux, struct cch_handle *handl if (ret < 0) { log_error("Failed to open input (%s).", av_err2str(ret)); av_dict_free(&opts); - goto err; + return false; } av_dict_free(&opts); @@ -75,12 +75,12 @@ static bool ff_demuxer_init(struct camu_demuxer *demux, struct cch_handle *handl ret = avformat_find_stream_info(av->format_context, NULL); if (ret < 0) { log_error("Failed to find stream info (%s).", av_err2str(ret)); - goto err; + return false; } if (!av->format_context->nb_streams) { log_error("No streams found."); - goto err; + return false; } s64 default_duration = (av->format_context->duration < 0) ? 0 : av->format_context->duration; @@ -143,9 +143,6 @@ static bool ff_demuxer_init(struct camu_demuxer *demux, struct cch_handle *handl av->eof = false; return true; -err: - close_internal(av); - return false; } static bool subscribed_to_index(struct camu_demuxer *demux, s32 index) diff --git a/src/codec/ffmpeg/resampler.c b/src/codec/ffmpeg/resampler.c index b141681..fa868c8 100644 --- a/src/codec/ffmpeg/resampler.c +++ b/src/codec/ffmpeg/resampler.c @@ -8,8 +8,9 @@ static bool ff_resampler_init(struct camu_resampler *resamp, struct camu_resampler_format *fmt) { struct camu_ff_resampler *av = (struct camu_ff_resampler *)resamp; - al_assert(fmt->resampler_needed); + av->resample_context = NULL; + al_assert(fmt->resampler_needed); camu_audio_format_copy(&av->fmt, &fmt->req); SwrContext *swr = swr_alloc(); diff --git a/src/fruits/cmsrv/ui.c b/src/fruits/cmsrv/ui.c index 1dd5fa2..e8fbc41 100644 --- a/src/fruits/cmsrv/ui.c +++ b/src/fruits/cmsrv/ui.c @@ -118,6 +118,7 @@ static void erase_lists(struct cmsrv_ui *ui) if (n) ncplane_erase(n); } +#ifdef CAMU_HAVE_PORTAL static void putnwstr_maxwidth_yx(struct ncplane *n, u32 y, u32 x, u32 maxwidth, wstr *w) { ncplane_cursor_move_yx(n, y, x); @@ -126,6 +127,7 @@ static void putnwstr_maxwidth_yx(struct ncplane *n, u32 y, u32 x, u32 maxwidth, ncplane_putwc(n, al_wstr_at(w, i)); } } +#endif static void render_lists(struct cmsrv_ui *ui) { diff --git a/src/server/server.c b/src/server/server.c index db55ae2..e76f6f4 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -330,7 +330,7 @@ static struct cch_entry *entry_from_post(struct camu_server *server, struct camu } } if (!entry) { - log_error("Failed to load post media %.*s %u.", al_str_x(&post->unique_id), index); + log_error("Failed to load media from post %.*s (index: %u).", al_str_x(&post->unique_id), index); return NULL; } entry->handler->maybe_spawn_worker(entry->handler, 0); @@ -467,7 +467,7 @@ static void list_callback(void *userdata, u8 op, struct lia_list_entry *entry, v send_clients_entry_seeked(server, list, entry); break; case LIANA_META_ENTRY_ERRORED: - log_error("Failed to load: %.*s.", al_str_x(&entry->brief)); + log_error("Errored: %.*s.", al_str_x(&entry->brief)); break; } break; diff --git a/tests/cue_splitter.c b/tests/cue_splitter.c index 9b6561d..b5a8627 100644 --- a/tests/cue_splitter.c +++ b/tests/cue_splitter.c @@ -185,7 +185,7 @@ s32 main(s32 argc, char *argv[]) al_str_clone(&output_path, &output_dir); al_str_cat(&output_path, &al_str_c("/")); al_str_cat(&output_path, &info->filename); - // start and length from libcue ignore all gaps. + // start and length from libcue ignores all gaps. info->start = track_get_start(track); info->length = track_get_length(track); al_printf("start: %zd, length: %zd, %.*s\n", info->start, info->length, al_str_x(&output_path)); @@ -195,8 +195,5 @@ s32 main(s32 argc, char *argv[]) return EXIT_SUCCESS; } #else -s32 main(void) -{ - return EXIT_FAILURE; -} +s32 main(void) { return EXIT_FAILURE; } #endif |