From a54600cb32e52298d39d97bb432db459a091293d Mon Sep 17 00:00:00 2001 From: xufuji456 <839789740@qq.com> Date: Sun, 31 Oct 2021 16:45:19 +0800 Subject: [PATCH] add ffmpeg_common.h --- app/CMakeLists.txt | 6 +- app/src/main/cpp/ffmpeg/ffmpeg.h | 543 +----------------------- app/src/main/cpp/ffmpeg/ffmpeg_common.h | 542 +++++++++++++++++++++++ app/src/main/cpp/ffmpeg/ffmpeg_hw.cpp | 226 +++++----- app/src/main/cpp/ffmpeg/ffmpeg_hw.h | 28 ++ 5 files changed, 688 insertions(+), 657 deletions(-) create mode 100644 app/src/main/cpp/ffmpeg/ffmpeg_common.h create mode 100644 app/src/main/cpp/ffmpeg/ffmpeg_hw.h diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 226ad0c..d77b13e 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -50,8 +50,8 @@ set_target_properties( ffmpeg ../../../../libs/${CMAKE_ANDROID_ARCH_ABI}/libffmpeg.so ) # third-party library: sox -add_subdirectory(src/main/cpp/sox) -include_directories(src/main/cpp/sox) +#add_subdirectory(src/main/cpp/sox) +#include_directories(src/main/cpp/sox) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11") @@ -72,7 +72,7 @@ find_library( # Sets the name of the path variable. target_link_libraries( # Specifies the target library. media-handle ffmpeg - sox +# sox -landroid #native_window -ljnigraphics #bitmap -lOpenSLES #openSLES diff --git a/app/src/main/cpp/ffmpeg/ffmpeg.h b/app/src/main/cpp/ffmpeg/ffmpeg.h index 7fef18a..564f291 100644 --- a/app/src/main/cpp/ffmpeg/ffmpeg.h +++ b/app/src/main/cpp/ffmpeg/ffmpeg.h @@ -22,35 +22,9 @@ #include #include #include -#ifdef __cplusplus -extern "C" { -#endif - -#include "cmdutils.h" -#include "config.h" - -#include "libavformat/avformat.h" -#include "libavformat/avio.h" - -#include "libavcodec/avcodec.h" +#include "ffmpeg_hw.h" +#include "ffmpeg_common.h" -#include "libavfilter/avfilter.h" - -#include "libavutil/avutil.h" -#include "libavutil/dict.h" -#include "libavutil/eval.h" -#include "libavutil/fifo.h" -#include "libavutil/hwcontext.h" -#include "libavutil/pixfmt.h" -#include "libavutil/rational.h" -#include "libavutil/thread.h" -#include "libavutil/threadmessage.h" - -#include "libswresample/swresample.h" - -#ifdef __cplusplus -} -#endif #define VSYNC_AUTO -1 #define VSYNC_PASSTHROUGH 0 #define VSYNC_CFR 1 @@ -60,515 +34,10 @@ extern "C" { #define MAX_STREAMS 1024 /* arbitrary sanity check value */ -enum HWAccelID { - HWACCEL_NONE = 0, - HWACCEL_AUTO, - HWACCEL_GENERIC, - HWACCEL_VIDEOTOOLBOX, - HWACCEL_QSV, - HWACCEL_CUVID, -}; - -typedef struct HWAccel { - const char *name; - int (*init)(AVCodecContext *s); - enum HWAccelID id; - enum AVPixelFormat pix_fmt; -} HWAccel; - -typedef struct HWDevice { - const char *name; - enum AVHWDeviceType type; - AVBufferRef *device_ref; -} HWDevice; - -/* select an input stream for an output stream */ -typedef struct StreamMap { - int disabled; /* 1 is this mapping is disabled by a negative map */ - int file_index; - int stream_index; - int sync_file_index; - int sync_stream_index; - char *linklabel; /* name of an output link, for mapping lavfi outputs */ -} StreamMap; - -typedef struct { - int file_idx, stream_idx, channel_idx; // input - int ofile_idx, ostream_idx; // output -} AudioChannelMap; - -typedef struct OptionsContext { - OptionGroup *g; - - /* input/output options */ - int64_t start_time; - int64_t start_time_eof; - int seek_timestamp; - const char *format; - - SpecifierOpt *codec_names; - int nb_codec_names; - SpecifierOpt *audio_channels; - int nb_audio_channels; - SpecifierOpt *audio_sample_rate; - int nb_audio_sample_rate; - SpecifierOpt *frame_rates; - int nb_frame_rates; - SpecifierOpt *frame_sizes; - int nb_frame_sizes; - SpecifierOpt *frame_pix_fmts; - int nb_frame_pix_fmts; - - /* input options */ - int64_t input_ts_offset; - int loop; - int rate_emu; - int accurate_seek; - int thread_queue_size; - - SpecifierOpt *ts_scale; - int nb_ts_scale; - SpecifierOpt *dump_attachment; - int nb_dump_attachment; - SpecifierOpt *hwaccels; - int nb_hwaccels; - SpecifierOpt *hwaccel_devices; - int nb_hwaccel_devices; - SpecifierOpt *hwaccel_output_formats; - int nb_hwaccel_output_formats; - SpecifierOpt *autorotate; - int nb_autorotate; - - /* output options */ - StreamMap *stream_maps; - int nb_stream_maps; - AudioChannelMap *audio_channel_maps; /* one info entry per -map_channel */ - int nb_audio_channel_maps; /* number of (valid) -map_channel settings */ - int metadata_global_manual; - int metadata_streams_manual; - int metadata_chapters_manual; - const char **attachments; - int nb_attachments; - - int chapters_input_file; - - int64_t recording_time; - int64_t stop_time; - uint64_t limit_filesize; - float mux_preload; - float mux_max_delay; - int shortest; - int bitexact; - - int video_disable; - int audio_disable; - int subtitle_disable; - int data_disable; - - /* indexed by output file stream index */ - int *streamid_map; - int nb_streamid_map; - - SpecifierOpt *metadata; - int nb_metadata; - SpecifierOpt *max_frames; - int nb_max_frames; - SpecifierOpt *bitstream_filters; - int nb_bitstream_filters; - SpecifierOpt *codec_tags; - int nb_codec_tags; - SpecifierOpt *sample_fmts; - int nb_sample_fmts; - SpecifierOpt *qscale; - int nb_qscale; - SpecifierOpt *forced_key_frames; - int nb_forced_key_frames; - SpecifierOpt *force_fps; - int nb_force_fps; - SpecifierOpt *frame_aspect_ratios; - int nb_frame_aspect_ratios; - SpecifierOpt *rc_overrides; - int nb_rc_overrides; - SpecifierOpt *intra_matrices; - int nb_intra_matrices; - SpecifierOpt *inter_matrices; - int nb_inter_matrices; - SpecifierOpt *chroma_intra_matrices; - int nb_chroma_intra_matrices; - SpecifierOpt *top_field_first; - int nb_top_field_first; - SpecifierOpt *metadata_map; - int nb_metadata_map; - SpecifierOpt *presets; - int nb_presets; - SpecifierOpt *copy_initial_nonkeyframes; - int nb_copy_initial_nonkeyframes; - SpecifierOpt *copy_prior_start; - int nb_copy_prior_start; - SpecifierOpt *filters; - int nb_filters; - SpecifierOpt *filter_scripts; - int nb_filter_scripts; - SpecifierOpt *reinit_filters; - int nb_reinit_filters; - SpecifierOpt *fix_sub_duration; - int nb_fix_sub_duration; - SpecifierOpt *canvas_sizes; - int nb_canvas_sizes; - SpecifierOpt *pass; - int nb_pass; - SpecifierOpt *passlogfiles; - int nb_passlogfiles; - SpecifierOpt *max_muxing_queue_size; - int nb_max_muxing_queue_size; - SpecifierOpt *guess_layout_max; - int nb_guess_layout_max; - SpecifierOpt *apad; - int nb_apad; - SpecifierOpt *discard; - int nb_discard; - SpecifierOpt *disposition; - int nb_disposition; - SpecifierOpt *program; - int nb_program; - SpecifierOpt *time_bases; - int nb_time_bases; - SpecifierOpt *enc_time_bases; - int nb_enc_time_bases; -} OptionsContext; - -typedef struct InputFilter { - AVFilterContext *filter; - struct InputStream *ist; - struct FilterGraph *graph; - uint8_t *name; - enum AVMediaType type; // AVMEDIA_TYPE_SUBTITLE for sub2video - - AVFifoBuffer *frame_queue; - - // parameters configured for this input - int format; - - int width, height; - AVRational sample_aspect_ratio; - - int sample_rate; - int channels; - uint64_t channel_layout; - - AVBufferRef *hw_frames_ctx; - - int eof; -} InputFilter; - -typedef struct OutputFilter { - AVFilterContext *filter; - struct OutputStream *ost; - struct FilterGraph *graph; - uint8_t *name; - - /* temporary storage until stream maps are processed */ - AVFilterInOut *out_tmp; - enum AVMediaType type; - - /* desired output stream properties */ - int width, height; - AVRational frame_rate; - int format; - int sample_rate; - uint64_t channel_layout; - - // those are only set if no format is specified and the encoder gives us multiple options - int *formats; - uint64_t *channel_layouts; - int *sample_rates; -} OutputFilter; - -typedef struct FilterGraph { - int index; - const char *graph_desc; - - AVFilterGraph *graph; - int reconfiguration; - - InputFilter **inputs; - int nb_inputs; - OutputFilter **outputs; - int nb_outputs; -} FilterGraph; - -typedef struct InputStream { - int file_index; - AVStream *st; - int discard; /* true if stream data should be discarded */ - int user_set_discard; - int decoding_needed; /* non zero if the packets must be decoded in 'raw_fifo', see DECODING_FOR_* */ -#define DECODING_FOR_OST 1 -#define DECODING_FOR_FILTER 2 - - AVCodecContext *dec_ctx; - AVCodec *dec; - AVFrame *decoded_frame; - AVFrame *filter_frame; /* a ref of decoded_frame, to be sent to filters */ - - int64_t start; /* time when read started */ - /* predicted dts of the next packet read for this stream or (when there are - * several frames in a packet) of the next frame in current packet (in AV_TIME_BASE units) */ - int64_t next_dts; - int64_t dts; ///< dts of the last packet read for this stream (in AV_TIME_BASE units) - - int64_t next_pts; ///< synthetic pts for the next decode frame (in AV_TIME_BASE units) - int64_t pts; ///< current pts of the decoded frame (in AV_TIME_BASE units) - int wrap_correction_done; - - int64_t filter_in_rescale_delta_last; - - int64_t min_pts; /* pts with the smallest value in a current stream */ - int64_t max_pts; /* pts with the higher value in a current stream */ - - // when forcing constant input framerate through -r, - // this contains the pts that will be given to the next decoded frame - int64_t cfr_next_pts; - - int64_t nb_samples; /* number of samples in the last decoded audio frame before looping */ - - double ts_scale; - int saw_first_ts; - AVDictionary *decoder_opts; - AVRational framerate; /* framerate forced with -r */ - int top_field_first; - int guess_layout_max; - - int autorotate; - - int fix_sub_duration; - struct { /* previous decoded subtitle and related variables */ - int got_output; - int ret; - AVSubtitle subtitle; - } prev_sub; - - struct sub2video { - int64_t last_pts; - int64_t end_pts; - AVFifoBuffer *sub_queue; ///< queue of AVSubtitle* before filter init - AVFrame *frame; - int w, h; - } sub2video; - - int dr1; - - /* decoded data from this stream goes into all those filters - * currently video and audio only */ - InputFilter **filters; - int nb_filters; - - int reinit_filters; - - /* hwaccel options */ - enum HWAccelID hwaccel_id; - enum AVHWDeviceType hwaccel_device_type; - char *hwaccel_device; - enum AVPixelFormat hwaccel_output_format; - - /* hwaccel context */ - void *hwaccel_ctx; - void (*hwaccel_uninit)(AVCodecContext *s); - int (*hwaccel_get_buffer)(AVCodecContext *s, AVFrame *frame, int flags); - int (*hwaccel_retrieve_data)(AVCodecContext *s, AVFrame *frame); - enum AVPixelFormat hwaccel_pix_fmt; - enum AVPixelFormat hwaccel_retrieved_pix_fmt; - AVBufferRef *hw_frames_ctx; - - /* stats */ - // combined size of all the packets read - uint64_t data_size; - /* number of packets successfully read for this stream */ - uint64_t nb_packets; - // number of frames/samples retrieved from the decoder - uint64_t frames_decoded; - uint64_t samples_decoded; - - int64_t *dts_buffer; - int nb_dts_buffer; - - int got_output; -} InputStream; - -typedef struct InputFile { - AVFormatContext *ctx; - int eof_reached; /* true if eof reached */ - int eagain; /* true if last read attempt returned EAGAIN */ - int ist_index; /* index of first stream in input_streams */ - int loop; /* set number of times input stream should be looped */ - int64_t duration; /* actual duration of the longest stream in a file - at the moment when looping happens */ - AVRational time_base; /* time base of the duration */ - int64_t input_ts_offset; - - int64_t ts_offset; - int64_t last_ts; - int64_t start_time; /* user-specified start time in AV_TIME_BASE or AV_NOPTS_VALUE */ - int seek_timestamp; - int64_t recording_time; - int nb_streams; /* number of stream that ffmpeg is aware of; may be different - from ctx.nb_streams if new streams appear during av_read_frame() */ - int nb_streams_warn; /* number of streams that the user was warned of */ - int rate_emu; - int accurate_seek; - -#if HAVE_THREADS - AVThreadMessageQueue *in_thread_queue; - pthread_t thread; /* thread reading from this file */ - int non_blocking; /* reading packets from the thread should not block */ - int joined; /* the thread has been joined */ - int thread_queue_size; /* maximum number of queued packets */ -#endif -} InputFile; - -enum forced_keyframes_const { - FKF_N, - FKF_N_FORCED, - FKF_PREV_FORCED_N, - FKF_PREV_FORCED_T, - FKF_T, - FKF_NB -}; - #define ABORT_ON_FLAG_EMPTY_OUTPUT (1 << 0) extern const char *const forced_keyframes_const_names[]; -typedef enum { - ENCODER_FINISHED = 1, - MUXER_FINISHED = 2, -} OSTFinished ; - -typedef struct OutputStream { - int file_index; /* file index */ - int index; /* stream index in the output file */ - int source_index; /* InputStream index */ - AVStream *st; /* stream in the output file */ - int encoding_needed; /* true if encoding needed for this stream */ - int frame_number; - /* input pts and corresponding output pts - for A/V sync */ - struct InputStream *sync_ist; /* input stream to sync against */ - int64_t sync_opts; /* output frame counter, could be changed to some true timestamp */ // FIXME look at frame_number - /* pts of the first frame encoded for this stream, used for limiting - * recording time */ - int64_t first_pts; - /* dts of the last packet sent to the muxer */ - int64_t last_mux_dts; - // the timebase of the packets sent to the muxer - AVRational mux_timebase; - AVRational enc_timebase; - - int nb_bitstream_filters; - AVBSFContext **bsf_ctx; - - AVCodecContext *enc_ctx; - AVCodecParameters *ref_par; /* associated input codec parameters with encoders options applied */ - AVCodec *enc; - int64_t max_frames; - AVFrame *filtered_frame; - AVFrame *last_frame; - int last_dropped; - int last_nb0_frames[3]; - - void *hwaccel_ctx; - - /* video only */ - AVRational frame_rate; - int is_cfr; - int force_fps; - int top_field_first; - int rotate_overridden; - double rotate_override_value; - - AVRational frame_aspect_ratio; - - /* forced key frames */ - int64_t forced_kf_ref_pts; - int64_t *forced_kf_pts; - int forced_kf_count; - int forced_kf_index; - char *forced_keyframes; - AVExpr *forced_keyframes_pexpr; - double forced_keyframes_expr_const_values[FKF_NB]; - - /* audio only */ - int *audio_channels_map; /* list of the channels id to pick from the source stream */ - int audio_channels_mapped; /* number of channels in audio_channels_map */ - - char *logfile_prefix; - FILE *logfile; - - OutputFilter *filter; - char *avfilter; - char *filters; ///< filtergraph associated to the -filter option - char *filters_script; ///< filtergraph script associated to the -filter_script option - - AVDictionary *encoder_opts; - AVDictionary *sws_dict; - AVDictionary *swr_opts; - AVDictionary *resample_opts; - char *apad; - OSTFinished finished; /* no more packets should be written for this stream */ - int unavailable; /* true if the steram is unavailable (possibly temporarily) */ - int stream_copy; - - // init_output_stream() has been called for this stream - // The encoder and the bitstream filters have been initialized and the stream - // parameters are set in the AVStream. - int initialized; - - int inputs_done; - - const char *attachment_filename; - int copy_initial_nonkeyframes; - int copy_prior_start; - char *disposition; - - int keep_pix_fmt; - - /* stats */ - // combined size of all the packets written - uint64_t data_size; - // number of packets send to the muxer - uint64_t packets_written; - // number of frames/samples sent to the encoder - uint64_t frames_encoded; - uint64_t samples_encoded; - - /* packet quality factor */ - int quality; - - int max_muxing_queue_size; - - /* the packets are buffered here until the muxer is ready to be initialized */ - AVFifoBuffer *muxing_queue; - - /* packet picture type */ - int pict_type; - - /* frame encode sum of squared error values */ - int64_t error[4]; -} OutputStream; - -typedef struct OutputFile { - AVFormatContext *ctx; - AVDictionary *opts; - int ost_index; /* index of the first stream in output_streams */ - int64_t recording_time; ///< desired length of the resulting file in microseconds == AV_TIME_BASE units - int64_t start_time; ///< start time in microseconds == AV_TIME_BASE units - uint64_t limit_filesize; /* filesize limit expressed in bytes */ - - int shortest; - - int header_written; -} OutputFile; - extern InputStream **input_streams; extern int nb_input_streams; extern InputFile **input_files; @@ -663,14 +132,6 @@ int videotoolbox_init(AVCodecContext *s); int qsv_init(AVCodecContext *s); int cuvid_init(AVCodecContext *s); -HWDevice *hw_device_get_by_name(const char *name); -int hw_device_init_from_string(const char *arg, HWDevice **dev); -void hw_device_free_all(void); - -int hw_device_setup_for_decode(InputStream *ist); -int hw_device_setup_for_encode(OutputStream *ost); - -int hwaccel_decode_init(AVCodecContext *avctx); #ifdef __cplusplus } #endif diff --git a/app/src/main/cpp/ffmpeg/ffmpeg_common.h b/app/src/main/cpp/ffmpeg/ffmpeg_common.h new file mode 100644 index 0000000..5136120 --- /dev/null +++ b/app/src/main/cpp/ffmpeg/ffmpeg_common.h @@ -0,0 +1,542 @@ +// +// Created by frank on 2021/10/31. +// + +#ifndef FFMPEGANDROID_FFMPEG_COMMON_H +#define FFMPEGANDROID_FFMPEG_COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "cmdutils.h" +#include "config.h" + +#include "libavformat/avformat.h" +#include "libavformat/avio.h" + +#include "libavcodec/avcodec.h" + +#include "libavfilter/avfilter.h" + +#include "libavutil/avutil.h" +#include "libavutil/dict.h" +#include "libavutil/eval.h" +#include "libavutil/fifo.h" +#include "libavutil/hwcontext.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" +#include "libavutil/thread.h" +#include "libavutil/threadmessage.h" + +#include "libswresample/swresample.h" +#ifdef __cplusplus +} +#endif + +enum forced_keyframes_const { + FKF_N, + FKF_N_FORCED, + FKF_PREV_FORCED_N, + FKF_PREV_FORCED_T, + FKF_T, + FKF_NB +}; + +typedef enum { + ENCODER_FINISHED = 1, + MUXER_FINISHED = 2, +} OSTFinished ; + +enum HWAccelID { + HWACCEL_NONE = 0, + HWACCEL_AUTO, + HWACCEL_GENERIC, + HWACCEL_VIDEOTOOLBOX, + HWACCEL_QSV, + HWACCEL_CUVID, +}; + +typedef struct HWAccel { + const char *name; + int (*init)(AVCodecContext *s); + enum HWAccelID id; + enum AVPixelFormat pix_fmt; +} HWAccel; + +typedef struct HWDevice { + const char *name; + enum AVHWDeviceType type; + AVBufferRef *device_ref; +} HWDevice; + +typedef struct InputFilter { + AVFilterContext *filter; + struct InputStream *ist; + struct FilterGraph *graph; + uint8_t *name; + enum AVMediaType type; // AVMEDIA_TYPE_SUBTITLE for sub2video + + AVFifoBuffer *frame_queue; + + // parameters configured for this input + int format; + + int width, height; + AVRational sample_aspect_ratio; + + int sample_rate; + int channels; + uint64_t channel_layout; + + AVBufferRef *hw_frames_ctx; + + int eof; +} InputFilter; + +typedef struct OutputFilter { + AVFilterContext *filter; + struct OutputStream *ost; + struct FilterGraph *graph; + uint8_t *name; + + /* temporary storage until stream maps are processed */ + AVFilterInOut *out_tmp; + enum AVMediaType type; + + /* desired output stream properties */ + int width, height; + AVRational frame_rate; + int format; + int sample_rate; + uint64_t channel_layout; + + // those are only set if no format is specified and the encoder gives us multiple options + int *formats; + uint64_t *channel_layouts; + int *sample_rates; +} OutputFilter; + +typedef struct InputStream { + int file_index; + AVStream *st; + int discard; /* true if stream data should be discarded */ + int user_set_discard; + int decoding_needed; /* non zero if the packets must be decoded in 'raw_fifo', see DECODING_FOR_* */ +#define DECODING_FOR_OST 1 +#define DECODING_FOR_FILTER 2 + + AVCodecContext *dec_ctx; + AVCodec *dec; + AVFrame *decoded_frame; + AVFrame *filter_frame; /* a ref of decoded_frame, to be sent to filters */ + + int64_t start; /* time when read started */ + /* predicted dts of the next packet read for this stream or (when there are + * several frames in a packet) of the next frame in current packet (in AV_TIME_BASE units) */ + int64_t next_dts; + int64_t dts; ///< dts of the last packet read for this stream (in AV_TIME_BASE units) + + int64_t next_pts; ///< synthetic pts for the next decode frame (in AV_TIME_BASE units) + int64_t pts; ///< current pts of the decoded frame (in AV_TIME_BASE units) + int wrap_correction_done; + + int64_t filter_in_rescale_delta_last; + + int64_t min_pts; /* pts with the smallest value in a current stream */ + int64_t max_pts; /* pts with the higher value in a current stream */ + + // when forcing constant input framerate through -r, + // this contains the pts that will be given to the next decoded frame + int64_t cfr_next_pts; + + int64_t nb_samples; /* number of samples in the last decoded audio frame before looping */ + + double ts_scale; + int saw_first_ts; + AVDictionary *decoder_opts; + AVRational framerate; /* framerate forced with -r */ + int top_field_first; + int guess_layout_max; + + int autorotate; + + int fix_sub_duration; + struct { /* previous decoded subtitle and related variables */ + int got_output; + int ret; + AVSubtitle subtitle; + } prev_sub; + + struct sub2video { + int64_t last_pts; + int64_t end_pts; + AVFifoBuffer *sub_queue; ///< queue of AVSubtitle* before filter init + AVFrame *frame; + int w, h; + } sub2video; + + int dr1; + + /* decoded data from this stream goes into all those filters + * currently video and audio only */ + InputFilter **filters; + int nb_filters; + + int reinit_filters; + + /* hwaccel options */ + enum HWAccelID hwaccel_id; + enum AVHWDeviceType hwaccel_device_type; + char *hwaccel_device; + enum AVPixelFormat hwaccel_output_format; + + /* hwaccel context */ + void *hwaccel_ctx; + void (*hwaccel_uninit)(AVCodecContext *s); + int (*hwaccel_get_buffer)(AVCodecContext *s, AVFrame *frame, int flags); + int (*hwaccel_retrieve_data)(AVCodecContext *s, AVFrame *frame); + enum AVPixelFormat hwaccel_pix_fmt; + enum AVPixelFormat hwaccel_retrieved_pix_fmt; + AVBufferRef *hw_frames_ctx; + + /* stats */ + // combined size of all the packets read + uint64_t data_size; + /* number of packets successfully read for this stream */ + uint64_t nb_packets; + // number of frames/samples retrieved from the decoder + uint64_t frames_decoded; + uint64_t samples_decoded; + + int64_t *dts_buffer; + int nb_dts_buffer; + + int got_output; +} InputStream; + +typedef struct OutputStream { + int file_index; /* file index */ + int index; /* stream index in the output file */ + int source_index; /* InputStream index */ + AVStream *st; /* stream in the output file */ + int encoding_needed; /* true if encoding needed for this stream */ + int frame_number; + /* input pts and corresponding output pts + for A/V sync */ + struct InputStream *sync_ist; /* input stream to sync against */ + int64_t sync_opts; /* output frame counter, could be changed to some true timestamp */ // FIXME look at frame_number + /* pts of the first frame encoded for this stream, used for limiting + * recording time */ + int64_t first_pts; + /* dts of the last packet sent to the muxer */ + int64_t last_mux_dts; + // the timebase of the packets sent to the muxer + AVRational mux_timebase; + AVRational enc_timebase; + + int nb_bitstream_filters; + AVBSFContext **bsf_ctx; + + AVCodecContext *enc_ctx; + AVCodecParameters *ref_par; /* associated input codec parameters with encoders options applied */ + AVCodec *enc; + int64_t max_frames; + AVFrame *filtered_frame; + AVFrame *last_frame; + int last_dropped; + int last_nb0_frames[3]; + + void *hwaccel_ctx; + + /* video only */ + AVRational frame_rate; + int is_cfr; + int force_fps; + int top_field_first; + int rotate_overridden; + double rotate_override_value; + + AVRational frame_aspect_ratio; + + /* forced key frames */ + int64_t forced_kf_ref_pts; + int64_t *forced_kf_pts; + int forced_kf_count; + int forced_kf_index; + char *forced_keyframes; + AVExpr *forced_keyframes_pexpr; + double forced_keyframes_expr_const_values[FKF_NB]; + + /* audio only */ + int *audio_channels_map; /* list of the channels id to pick from the source stream */ + int audio_channels_mapped; /* number of channels in audio_channels_map */ + + char *logfile_prefix; + FILE *logfile; + + OutputFilter *filter; + char *avfilter; + char *filters; ///< filtergraph associated to the -filter option + char *filters_script; ///< filtergraph script associated to the -filter_script option + + AVDictionary *encoder_opts; + AVDictionary *sws_dict; + AVDictionary *swr_opts; + AVDictionary *resample_opts; + char *apad; + OSTFinished finished; /* no more packets should be written for this stream */ + int unavailable; /* true if the steram is unavailable (possibly temporarily) */ + int stream_copy; + + // init_output_stream() has been called for this stream + // The encoder and the bitstream filters have been initialized and the stream + // parameters are set in the AVStream. + int initialized; + + int inputs_done; + + const char *attachment_filename; + int copy_initial_nonkeyframes; + int copy_prior_start; + char *disposition; + + int keep_pix_fmt; + + /* stats */ + // combined size of all the packets written + uint64_t data_size; + // number of packets send to the muxer + uint64_t packets_written; + // number of frames/samples sent to the encoder + uint64_t frames_encoded; + uint64_t samples_encoded; + + /* packet quality factor */ + int quality; + + int max_muxing_queue_size; + + /* the packets are buffered here until the muxer is ready to be initialized */ + AVFifoBuffer *muxing_queue; + + /* packet picture type */ + int pict_type; + + /* frame encode sum of squared error values */ + int64_t error[4]; +} OutputStream; + +/* select an input stream for an output stream */ +typedef struct StreamMap { + int disabled; /* 1 is this mapping is disabled by a negative map */ + int file_index; + int stream_index; + int sync_file_index; + int sync_stream_index; + char *linklabel; /* name of an output link, for mapping lavfi outputs */ +} StreamMap; + +typedef struct { + int file_idx, stream_idx, channel_idx; // input + int ofile_idx, ostream_idx; // output +} AudioChannelMap; + +typedef struct OptionsContext { + OptionGroup *g; + + /* input/output options */ + int64_t start_time; + int64_t start_time_eof; + int seek_timestamp; + const char *format; + + SpecifierOpt *codec_names; + int nb_codec_names; + SpecifierOpt *audio_channels; + int nb_audio_channels; + SpecifierOpt *audio_sample_rate; + int nb_audio_sample_rate; + SpecifierOpt *frame_rates; + int nb_frame_rates; + SpecifierOpt *frame_sizes; + int nb_frame_sizes; + SpecifierOpt *frame_pix_fmts; + int nb_frame_pix_fmts; + + /* input options */ + int64_t input_ts_offset; + int loop; + int rate_emu; + int accurate_seek; + int thread_queue_size; + + SpecifierOpt *ts_scale; + int nb_ts_scale; + SpecifierOpt *dump_attachment; + int nb_dump_attachment; + SpecifierOpt *hwaccels; + int nb_hwaccels; + SpecifierOpt *hwaccel_devices; + int nb_hwaccel_devices; + SpecifierOpt *hwaccel_output_formats; + int nb_hwaccel_output_formats; + SpecifierOpt *autorotate; + int nb_autorotate; + + /* output options */ + StreamMap *stream_maps; + int nb_stream_maps; + AudioChannelMap *audio_channel_maps; /* one info entry per -map_channel */ + int nb_audio_channel_maps; /* number of (valid) -map_channel settings */ + int metadata_global_manual; + int metadata_streams_manual; + int metadata_chapters_manual; + const char **attachments; + int nb_attachments; + + int chapters_input_file; + + int64_t recording_time; + int64_t stop_time; + uint64_t limit_filesize; + float mux_preload; + float mux_max_delay; + int shortest; + int bitexact; + + int video_disable; + int audio_disable; + int subtitle_disable; + int data_disable; + + /* indexed by output file stream index */ + int *streamid_map; + int nb_streamid_map; + + SpecifierOpt *metadata; + int nb_metadata; + SpecifierOpt *max_frames; + int nb_max_frames; + SpecifierOpt *bitstream_filters; + int nb_bitstream_filters; + SpecifierOpt *codec_tags; + int nb_codec_tags; + SpecifierOpt *sample_fmts; + int nb_sample_fmts; + SpecifierOpt *qscale; + int nb_qscale; + SpecifierOpt *forced_key_frames; + int nb_forced_key_frames; + SpecifierOpt *force_fps; + int nb_force_fps; + SpecifierOpt *frame_aspect_ratios; + int nb_frame_aspect_ratios; + SpecifierOpt *rc_overrides; + int nb_rc_overrides; + SpecifierOpt *intra_matrices; + int nb_intra_matrices; + SpecifierOpt *inter_matrices; + int nb_inter_matrices; + SpecifierOpt *chroma_intra_matrices; + int nb_chroma_intra_matrices; + SpecifierOpt *top_field_first; + int nb_top_field_first; + SpecifierOpt *metadata_map; + int nb_metadata_map; + SpecifierOpt *presets; + int nb_presets; + SpecifierOpt *copy_initial_nonkeyframes; + int nb_copy_initial_nonkeyframes; + SpecifierOpt *copy_prior_start; + int nb_copy_prior_start; + SpecifierOpt *filters; + int nb_filters; + SpecifierOpt *filter_scripts; + int nb_filter_scripts; + SpecifierOpt *reinit_filters; + int nb_reinit_filters; + SpecifierOpt *fix_sub_duration; + int nb_fix_sub_duration; + SpecifierOpt *canvas_sizes; + int nb_canvas_sizes; + SpecifierOpt *pass; + int nb_pass; + SpecifierOpt *passlogfiles; + int nb_passlogfiles; + SpecifierOpt *max_muxing_queue_size; + int nb_max_muxing_queue_size; + SpecifierOpt *guess_layout_max; + int nb_guess_layout_max; + SpecifierOpt *apad; + int nb_apad; + SpecifierOpt *discard; + int nb_discard; + SpecifierOpt *disposition; + int nb_disposition; + SpecifierOpt *program; + int nb_program; + SpecifierOpt *time_bases; + int nb_time_bases; + SpecifierOpt *enc_time_bases; + int nb_enc_time_bases; +} OptionsContext; + +typedef struct FilterGraph { + int index; + const char *graph_desc; + + AVFilterGraph *graph; + int reconfiguration; + + InputFilter **inputs; + int nb_inputs; + OutputFilter **outputs; + int nb_outputs; +} FilterGraph; + +typedef struct InputFile { + AVFormatContext *ctx; + int eof_reached; /* true if eof reached */ + int eagain; /* true if last read attempt returned EAGAIN */ + int ist_index; /* index of first stream in input_streams */ + int loop; /* set number of times input stream should be looped */ + int64_t duration; /* actual duration of the longest stream in a file + at the moment when looping happens */ + AVRational time_base; /* time base of the duration */ + int64_t input_ts_offset; + + int64_t ts_offset; + int64_t last_ts; + int64_t start_time; /* user-specified start time in AV_TIME_BASE or AV_NOPTS_VALUE */ + int seek_timestamp; + int64_t recording_time; + int nb_streams; /* number of stream that ffmpeg is aware of; may be different + from ctx.nb_streams if new streams appear during av_read_frame() */ + int nb_streams_warn; /* number of streams that the user was warned of */ + int rate_emu; + int accurate_seek; + +#if HAVE_THREADS + AVThreadMessageQueue *in_thread_queue; + pthread_t thread; /* thread reading from this file */ + int non_blocking; /* reading packets from the thread should not block */ + int joined; /* the thread has been joined */ + int thread_queue_size; /* maximum number of queued packets */ +#endif +} InputFile; + +typedef struct OutputFile { + AVFormatContext *ctx; + AVDictionary *opts; + int ost_index; /* index of the first stream in output_streams */ + int64_t recording_time; ///< desired length of the resulting file in microseconds == AV_TIME_BASE units + int64_t start_time; ///< start time in microseconds == AV_TIME_BASE units + uint64_t limit_filesize; /* filesize limit expressed in bytes */ + + int shortest; + + int header_written; +} OutputFile; + +#endif //FFMPEGANDROID_FFMPEG_COMMON_H diff --git a/app/src/main/cpp/ffmpeg/ffmpeg_hw.cpp b/app/src/main/cpp/ffmpeg/ffmpeg_hw.cpp index da39204..ee26059 100644 --- a/app/src/main/cpp/ffmpeg/ffmpeg_hw.cpp +++ b/app/src/main/cpp/ffmpeg/ffmpeg_hw.cpp @@ -17,6 +17,7 @@ */ #include +#include "ffmpeg_hw.h" #ifdef __cplusplus extern "C" { #endif @@ -24,7 +25,6 @@ extern "C" { #ifdef __cplusplus } #endif -#include "ffmpeg.h" static int nb_hw_devices; static HWDevice **hw_devices; @@ -43,16 +43,6 @@ static HWDevice *hw_device_get_by_type(enum AVHWDeviceType type) return found; } -HWDevice *hw_device_get_by_name(const char *name) -{ - int i; - for (i = 0; i < nb_hw_devices; i++) { - if (!strcmp(hw_devices[i]->name, name)) - return hw_devices[i]; - } - return NULL; -} - static HWDevice *hw_device_add(void) { int err; @@ -93,6 +83,118 @@ static char *hw_device_default_name(enum AVHWDeviceType type) return name; } +static int hw_device_init_from_type(enum AVHWDeviceType type, + const char *device, + HWDevice **dev_out) +{ + AVBufferRef *device_ref = NULL; + HWDevice *dev; + char *name; + int err; + + name = hw_device_default_name(type); + if (!name) { + err = AVERROR(ENOMEM); + goto fail; + } + + err = av_hwdevice_ctx_create(&device_ref, type, device, NULL, 0); + if (err < 0) { + av_log(NULL, AV_LOG_ERROR, + "Device creation failed: %d.\n", err); + goto fail; + } + + dev = hw_device_add(); + if (!dev) { + err = AVERROR(ENOMEM); + goto fail; + } + + dev->name = name; + dev->type = type; + dev->device_ref = device_ref; + + if (dev_out) + *dev_out = dev; + + return 0; + + fail: + av_freep(&name); + av_buffer_unref(&device_ref); + return err; +} + +static HWDevice *hw_device_match_by_codec(const AVCodec *codec) +{ + const AVCodecHWConfig *config; + HWDevice *dev; + int i; + for (i = 0;; i++) { + config = avcodec_get_hw_config(codec, i); + if (!config) + return NULL; + if (!(config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)) + continue; + dev = hw_device_get_by_type(config->device_type); + if (dev) + return dev; + } +} + +static int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input) +{ + InputStream *ist = static_cast(avctx->opaque); + AVFrame *output = NULL; + enum AVPixelFormat output_format = ist->hwaccel_output_format; + int err; + + if (input->format == output_format) { + // Nothing to do. + return 0; + } + + output = av_frame_alloc(); + if (!output) + return AVERROR(ENOMEM); + + output->format = output_format; + + err = av_hwframe_transfer_data(output, input, 0); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to transfer data to " + "output frame: %d.\n", err); + goto fail; + } + + err = av_frame_copy_props(output, input); + if (err < 0) { + av_frame_unref(output); + goto fail; + } + + av_frame_unref(input); + av_frame_move_ref(input, output); + av_frame_free(&output); + + return 0; + + fail: + av_frame_free(&output); + return err; +} + +HWDevice *hw_device_get_by_name(const char *name) +{ + int i; + for (i = 0; i < nb_hw_devices; i++) { + if (!strcmp(hw_devices[i]->name, name)) + return hw_devices[i]; + } + return NULL; +} + int hw_device_init_from_string(const char *arg, HWDevice **dev_out) { // "type=name:device,key=value,key2=value2" @@ -230,49 +332,6 @@ fail: goto done; } -static int hw_device_init_from_type(enum AVHWDeviceType type, - const char *device, - HWDevice **dev_out) -{ - AVBufferRef *device_ref = NULL; - HWDevice *dev; - char *name; - int err; - - name = hw_device_default_name(type); - if (!name) { - err = AVERROR(ENOMEM); - goto fail; - } - - err = av_hwdevice_ctx_create(&device_ref, type, device, NULL, 0); - if (err < 0) { - av_log(NULL, AV_LOG_ERROR, - "Device creation failed: %d.\n", err); - goto fail; - } - - dev = hw_device_add(); - if (!dev) { - err = AVERROR(ENOMEM); - goto fail; - } - - dev->name = name; - dev->type = type; - dev->device_ref = device_ref; - - if (dev_out) - *dev_out = dev; - - return 0; - -fail: - av_freep(&name); - av_buffer_unref(&device_ref); - return err; -} - void hw_device_free_all(void) { int i; @@ -285,23 +344,6 @@ void hw_device_free_all(void) nb_hw_devices = 0; } -static HWDevice *hw_device_match_by_codec(const AVCodec *codec) -{ - const AVCodecHWConfig *config; - HWDevice *dev; - int i; - for (i = 0;; i++) { - config = avcodec_get_hw_config(codec, i); - if (!config) - return NULL; - if (!(config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)) - continue; - dev = hw_device_get_by_type(config->device_type); - if (dev) - return dev; - } -} - int hw_device_setup_for_decode(InputStream *ist) { const AVCodecHWConfig *config; @@ -434,48 +476,6 @@ int hw_device_setup_for_encode(OutputStream *ost) } } -static int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input) -{ - InputStream *ist = static_cast(avctx->opaque); - AVFrame *output = NULL; - enum AVPixelFormat output_format = ist->hwaccel_output_format; - int err; - - if (input->format == output_format) { - // Nothing to do. - return 0; - } - - output = av_frame_alloc(); - if (!output) - return AVERROR(ENOMEM); - - output->format = output_format; - - err = av_hwframe_transfer_data(output, input, 0); - if (err < 0) { - av_log(avctx, AV_LOG_ERROR, "Failed to transfer data to " - "output frame: %d.\n", err); - goto fail; - } - - err = av_frame_copy_props(output, input); - if (err < 0) { - av_frame_unref(output); - goto fail; - } - - av_frame_unref(input); - av_frame_move_ref(input, output); - av_frame_free(&output); - - return 0; - -fail: - av_frame_free(&output); - return err; -} - int hwaccel_decode_init(AVCodecContext *avctx) { InputStream *ist = static_cast(avctx->opaque); diff --git a/app/src/main/cpp/ffmpeg/ffmpeg_hw.h b/app/src/main/cpp/ffmpeg/ffmpeg_hw.h new file mode 100644 index 0000000..25c0281 --- /dev/null +++ b/app/src/main/cpp/ffmpeg/ffmpeg_hw.h @@ -0,0 +1,28 @@ +// +// Created by frank on 2021/10/31. +// + +#ifndef FFMPEGANDROID_FFMPEG_HW_H +#define FFMPEGANDROID_FFMPEG_HW_H + +#include "ffmpeg_common.h" + +#ifdef __cplusplus +extern "C" { +#endif +HWDevice *hw_device_get_by_name(const char *name); + +int hw_device_init_from_string(const char *arg, HWDevice **dev_out); + +void hw_device_free_all(void); + +int hw_device_setup_for_decode(InputStream *ist); + +int hw_device_setup_for_encode(OutputStream *ost); + +int hwaccel_decode_init(AVCodecContext *avctx); +#ifdef __cplusplus +} +#endif + +#endif //FFMPEGANDROID_FFMPEG_HW_H