mirror of
				https://github.com/nyanmisaka/ffmpeg-rockchip.git
				synced 2025-10-31 04:26:37 +08:00 
			
		
		
		
	lavc: add a new bitstream filtering API
Deprecate the current bitstream filtering API.
This commit is contained in:
		
							
								
								
									
										2
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								configure
									
									
									
									
										vendored
									
									
								
							| @@ -2517,7 +2517,6 @@ ENCODER_LIST=$(find_things  encoder  ENC      libavcodec/allcodecs.c) | |||||||
| DECODER_LIST=$(find_things  decoder  DEC      libavcodec/allcodecs.c) | DECODER_LIST=$(find_things  decoder  DEC      libavcodec/allcodecs.c) | ||||||
| HWACCEL_LIST=$(find_things  hwaccel  HWACCEL  libavcodec/allcodecs.c) | HWACCEL_LIST=$(find_things  hwaccel  HWACCEL  libavcodec/allcodecs.c) | ||||||
| PARSER_LIST=$(find_things   parser   PARSER   libavcodec/allcodecs.c) | PARSER_LIST=$(find_things   parser   PARSER   libavcodec/allcodecs.c) | ||||||
| BSF_LIST=$(find_things      bsf      BSF      libavcodec/allcodecs.c) |  | ||||||
| MUXER_LIST=$(find_things    muxer    _MUX     libavformat/allformats.c) | MUXER_LIST=$(find_things    muxer    _MUX     libavformat/allformats.c) | ||||||
| DEMUXER_LIST=$(find_things  demuxer  DEMUX    libavformat/allformats.c) | DEMUXER_LIST=$(find_things  demuxer  DEMUX    libavformat/allformats.c) | ||||||
| OUTDEV_LIST=$(find_things   outdev   OUTDEV   libavdevice/alldevices.c) | OUTDEV_LIST=$(find_things   outdev   OUTDEV   libavdevice/alldevices.c) | ||||||
| @@ -2531,6 +2530,7 @@ find_things_extern(){ | |||||||
|     sed -n "s/^[^#]*extern.*$pattern *ff_\([^ ]*\)_$thing;/\1_$thing/p" "$file" |     sed -n "s/^[^#]*extern.*$pattern *ff_\([^ ]*\)_$thing;/\1_$thing/p" "$file" | ||||||
| } | } | ||||||
|  |  | ||||||
|  | BSF_LIST=$(find_things_extern bsf AVBitStreamFilter libavcodec/bitstream_filters.c) | ||||||
| PROTOCOL_LIST=$(find_things_extern protocol URLProtocol libavformat/protocols.c) | PROTOCOL_LIST=$(find_things_extern protocol URLProtocol libavformat/protocols.c) | ||||||
|  |  | ||||||
| ALL_COMPONENTS=" | ALL_COMPONENTS=" | ||||||
|   | |||||||
| @@ -13,6 +13,10 @@ libavutil:     2015-08-28 | |||||||
|  |  | ||||||
| API changes, most recent first: | API changes, most recent first: | ||||||
|  |  | ||||||
|  | 2016-xx-xx - xxxxxxx - lavc 57.15.0 - avcodec.h | ||||||
|  |   Add a new bitstream filtering API working with AVPackets. | ||||||
|  |   Deprecate the old bistream filtering API. | ||||||
|  |  | ||||||
| 2016-xx-xx - xxxxxxx - lavfi 6.3.0 - avfilter.h | 2016-xx-xx - xxxxxxx - lavfi 6.3.0 - avfilter.h | ||||||
|   Add AVFilterContext.hw_device_ctx. |   Add AVFilterContext.hw_device_ctx. | ||||||
|  |  | ||||||
|   | |||||||
| @@ -19,6 +19,8 @@ OBJS = allcodecs.o                                                      \ | |||||||
|        avpicture.o                                                      \ |        avpicture.o                                                      \ | ||||||
|        bitstream.o                                                      \ |        bitstream.o                                                      \ | ||||||
|        bitstream_filter.o                                               \ |        bitstream_filter.o                                               \ | ||||||
|  |        bitstream_filters.o                                              \ | ||||||
|  |        bsf.o                                                            \ | ||||||
|        codec_desc.o                                                     \ |        codec_desc.o                                                     \ | ||||||
|        d3d11va.o                                                        \ |        d3d11va.o                                                        \ | ||||||
|        dirac.o                                                          \ |        dirac.o                                                          \ | ||||||
|   | |||||||
| @@ -21,6 +21,7 @@ | |||||||
|  |  | ||||||
| #include "avcodec.h" | #include "avcodec.h" | ||||||
| #include "aacadtsdec.h" | #include "aacadtsdec.h" | ||||||
|  | #include "bsf.h" | ||||||
| #include "put_bits.h" | #include "put_bits.h" | ||||||
| #include "get_bits.h" | #include "get_bits.h" | ||||||
| #include "mpeg4audio.h" | #include "mpeg4audio.h" | ||||||
| @@ -34,65 +35,76 @@ typedef struct AACBSFContext { | |||||||
|  * This filter creates an MPEG-4 AudioSpecificConfig from an MPEG-2/4 |  * This filter creates an MPEG-4 AudioSpecificConfig from an MPEG-2/4 | ||||||
|  * ADTS header and removes the ADTS header. |  * ADTS header and removes the ADTS header. | ||||||
|  */ |  */ | ||||||
| static int aac_adtstoasc_filter(AVBitStreamFilterContext *bsfc, | static int aac_adtstoasc_filter(AVBSFContext *bsfc, AVPacket *out) | ||||||
|                                 AVCodecContext *avctx, const char *args, |  | ||||||
|                                 uint8_t  **poutbuf, int *poutbuf_size, |  | ||||||
|                                 const uint8_t *buf, int      buf_size, |  | ||||||
|                                 int keyframe) |  | ||||||
| { | { | ||||||
|  |     AACBSFContext *ctx = bsfc->priv_data; | ||||||
|  |  | ||||||
|     GetBitContext gb; |     GetBitContext gb; | ||||||
|     PutBitContext pb; |     PutBitContext pb; | ||||||
|     AACADTSHeaderInfo hdr; |     AACADTSHeaderInfo hdr; | ||||||
|  |     AVPacket *in; | ||||||
|  |     int ret; | ||||||
|  |  | ||||||
|     AACBSFContext *ctx = bsfc->priv_data; |     ret = ff_bsf_get_packet(bsfc, &in); | ||||||
|  |     if (ret < 0) | ||||||
|  |         return ret; | ||||||
|  |  | ||||||
|     init_get_bits(&gb, buf, AAC_ADTS_HEADER_SIZE*8); |     if (in->size < AAC_ADTS_HEADER_SIZE) | ||||||
|  |         goto packet_too_small; | ||||||
|  |  | ||||||
|     *poutbuf = (uint8_t*) buf; |     init_get_bits(&gb, in->data, AAC_ADTS_HEADER_SIZE * 8); | ||||||
|     *poutbuf_size = buf_size; |  | ||||||
|  |  | ||||||
|     if (avctx->extradata) |     if (bsfc->par_in->extradata && show_bits(&gb, 12) != 0xfff) | ||||||
|         if (show_bits(&gb, 12) != 0xfff) |         goto finish; | ||||||
|             return 0; |  | ||||||
|  |  | ||||||
|     if (avpriv_aac_parse_header(&gb, &hdr) < 0) { |     if (avpriv_aac_parse_header(&gb, &hdr) < 0) { | ||||||
|         av_log(avctx, AV_LOG_ERROR, "Error parsing ADTS frame header!\n"); |         av_log(bsfc, AV_LOG_ERROR, "Error parsing ADTS frame header!\n"); | ||||||
|         return AVERROR_INVALIDDATA; |         ret = AVERROR_INVALIDDATA; | ||||||
|  |         goto fail; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!hdr.crc_absent && hdr.num_aac_frames > 1) { |     if (!hdr.crc_absent && hdr.num_aac_frames > 1) { | ||||||
|         avpriv_report_missing_feature(avctx, |         avpriv_report_missing_feature(bsfc, | ||||||
|                                       "Multiple RDBs per frame with CRC"); |                                       "Multiple RDBs per frame with CRC"); | ||||||
|         return AVERROR_PATCHWELCOME; |         ret = AVERROR_PATCHWELCOME; | ||||||
|  |         goto fail; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     buf      += AAC_ADTS_HEADER_SIZE + 2*!hdr.crc_absent; |     in->size -= AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent; | ||||||
|     buf_size -= AAC_ADTS_HEADER_SIZE + 2*!hdr.crc_absent; |     if (in->size <= 0) | ||||||
|  |         goto packet_too_small; | ||||||
|  |     in->data += AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent; | ||||||
|  |  | ||||||
|     if (!ctx->first_frame_done) { |     if (!ctx->first_frame_done) { | ||||||
|         int            pce_size = 0; |         int            pce_size = 0; | ||||||
|         uint8_t        pce_data[MAX_PCE_SIZE]; |         uint8_t        pce_data[MAX_PCE_SIZE]; | ||||||
|  |         uint8_t       *extradata; | ||||||
|  |  | ||||||
|         if (!hdr.chan_config) { |         if (!hdr.chan_config) { | ||||||
|             init_get_bits(&gb, buf, buf_size * 8); |             init_get_bits(&gb, in->data, in->size * 8); | ||||||
|             if (get_bits(&gb, 3) != 5) { |             if (get_bits(&gb, 3) != 5) { | ||||||
|                 avpriv_report_missing_feature(avctx, |                 avpriv_report_missing_feature(bsfc, | ||||||
|                                               "PCE-based channel configuration " |                                               "PCE-based channel configuration " | ||||||
|                                               "without PCE as first syntax " |                                               "without PCE as first syntax " | ||||||
|                                               "element"); |                                               "element"); | ||||||
|                 return AVERROR_PATCHWELCOME; |                 ret = AVERROR_PATCHWELCOME; | ||||||
|  |                 goto fail; | ||||||
|             } |             } | ||||||
|             init_put_bits(&pb, pce_data, MAX_PCE_SIZE); |             init_put_bits(&pb, pce_data, MAX_PCE_SIZE); | ||||||
|             pce_size = avpriv_copy_pce_data(&pb, &gb)/8; |             pce_size = avpriv_copy_pce_data(&pb, &gb)/8; | ||||||
|             flush_put_bits(&pb); |             flush_put_bits(&pb); | ||||||
|             buf_size -= get_bits_count(&gb)/8; |             in->size -= get_bits_count(&gb)/8; | ||||||
|             buf      += get_bits_count(&gb)/8; |             in->data += get_bits_count(&gb)/8; | ||||||
|         } |         } | ||||||
|         avctx->extradata_size = 2 + pce_size; |  | ||||||
|         avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); |  | ||||||
|         if (!avctx->extradata) |  | ||||||
|             return AVERROR(ENOMEM); |  | ||||||
|  |  | ||||||
|         init_put_bits(&pb, avctx->extradata, avctx->extradata_size); |         extradata = av_packet_new_side_data(in, AV_PKT_DATA_NEW_EXTRADATA, | ||||||
|  |                                             2 + pce_size); | ||||||
|  |         if (!extradata) { | ||||||
|  |             ret = AVERROR(ENOMEM); | ||||||
|  |             goto fail; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         init_put_bits(&pb, extradata, 2 + pce_size); | ||||||
|         put_bits(&pb, 5, hdr.object_type); |         put_bits(&pb, 5, hdr.object_type); | ||||||
|         put_bits(&pb, 4, hdr.sampling_index); |         put_bits(&pb, 4, hdr.sampling_index); | ||||||
|         put_bits(&pb, 4, hdr.chan_config); |         put_bits(&pb, 4, hdr.chan_config); | ||||||
| @@ -101,20 +113,42 @@ static int aac_adtstoasc_filter(AVBitStreamFilterContext *bsfc, | |||||||
|         put_bits(&pb, 1, 0); //is not extension |         put_bits(&pb, 1, 0); //is not extension | ||||||
|         flush_put_bits(&pb); |         flush_put_bits(&pb); | ||||||
|         if (pce_size) { |         if (pce_size) { | ||||||
|             memcpy(avctx->extradata + 2, pce_data, pce_size); |             memcpy(extradata + 2, pce_data, pce_size); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         ctx->first_frame_done = 1; |         ctx->first_frame_done = 1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     *poutbuf = (uint8_t*) buf; | finish: | ||||||
|     *poutbuf_size = buf_size; |     av_packet_move_ref(out, in); | ||||||
|  |     av_packet_free(&in); | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  |  | ||||||
|  | packet_too_small: | ||||||
|  |     av_log(bsfc, AV_LOG_ERROR, "Input packet too small\n"); | ||||||
|  |     ret = AVERROR_INVALIDDATA; | ||||||
|  | fail: | ||||||
|  |     av_packet_free(&in); | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int aac_adtstoasc_init(AVBSFContext *ctx) | ||||||
|  | { | ||||||
|  |     av_freep(&ctx->par_out->extradata); | ||||||
|  |     ctx->par_out->extradata_size = 0; | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| AVBitStreamFilter ff_aac_adtstoasc_bsf = { | static const enum AVCodecID codec_ids[] = { | ||||||
|     "aac_adtstoasc", |     AV_CODEC_ID_AAC, AV_CODEC_ID_NONE, | ||||||
|     sizeof(AACBSFContext), | }; | ||||||
|     aac_adtstoasc_filter, |  | ||||||
|  | const AVBitStreamFilter ff_aac_adtstoasc_bsf = { | ||||||
|  |     .name           = "aac_adtstoasc", | ||||||
|  |     .priv_data_size = sizeof(AACBSFContext), | ||||||
|  |     .init           = aac_adtstoasc_init, | ||||||
|  |     .filter         = aac_adtstoasc_filter, | ||||||
|  |     .codec_ids      = codec_ids, | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -58,13 +58,6 @@ | |||||||
|             av_register_codec_parser(&ff_##x##_parser);                 \ |             av_register_codec_parser(&ff_##x##_parser);                 \ | ||||||
|     } |     } | ||||||
|  |  | ||||||
| #define REGISTER_BSF(X, x)                                              \ |  | ||||||
|     {                                                                   \ |  | ||||||
|         extern AVBitStreamFilter ff_##x##_bsf;                          \ |  | ||||||
|         if (CONFIG_##X##_BSF)                                           \ |  | ||||||
|             av_register_bitstream_filter(&ff_##x##_bsf);                \ |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| void avcodec_register_all(void) | void avcodec_register_all(void) | ||||||
| { | { | ||||||
|     static int initialized; |     static int initialized; | ||||||
| @@ -536,18 +529,4 @@ void avcodec_register_all(void) | |||||||
|     REGISTER_PARSER(VORBIS,             vorbis); |     REGISTER_PARSER(VORBIS,             vorbis); | ||||||
|     REGISTER_PARSER(VP3,                vp3); |     REGISTER_PARSER(VP3,                vp3); | ||||||
|     REGISTER_PARSER(VP8,                vp8); |     REGISTER_PARSER(VP8,                vp8); | ||||||
|  |  | ||||||
|     /* bitstream filters */ |  | ||||||
|     REGISTER_BSF(AAC_ADTSTOASC,         aac_adtstoasc); |  | ||||||
|     REGISTER_BSF(CHOMP,                 chomp); |  | ||||||
|     REGISTER_BSF(DUMP_EXTRADATA,        dump_extradata); |  | ||||||
|     REGISTER_BSF(H264_MP4TOANNEXB,      h264_mp4toannexb); |  | ||||||
|     REGISTER_BSF(HEVC_MP4TOANNEXB,      hevc_mp4toannexb); |  | ||||||
|     REGISTER_BSF(IMX_DUMP_HEADER,       imx_dump_header); |  | ||||||
|     REGISTER_BSF(MJPEG2JPEG,            mjpeg2jpeg); |  | ||||||
|     REGISTER_BSF(MJPEGA_DUMP_HEADER,    mjpega_dump_header); |  | ||||||
|     REGISTER_BSF(MOV2TEXTSUB,           mov2textsub); |  | ||||||
|     REGISTER_BSF(NOISE,                 noise); |  | ||||||
|     REGISTER_BSF(REMOVE_EXTRADATA,      remove_extradata); |  | ||||||
|     REGISTER_BSF(TEXT2MOVSUB,           text2movsub); |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4692,35 +4692,221 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes); | |||||||
|  */ |  */ | ||||||
| int av_get_audio_frame_duration2(AVCodecParameters *par, int frame_bytes); | int av_get_audio_frame_duration2(AVCodecParameters *par, int frame_bytes); | ||||||
|  |  | ||||||
|  | #if FF_API_OLD_BSF | ||||||
| typedef struct AVBitStreamFilterContext { | typedef struct AVBitStreamFilterContext { | ||||||
|     void *priv_data; |     void *priv_data; | ||||||
|     struct AVBitStreamFilter *filter; |     struct AVBitStreamFilter *filter; | ||||||
|     AVCodecParserContext *parser; |     AVCodecParserContext *parser; | ||||||
|     struct AVBitStreamFilterContext *next; |     struct AVBitStreamFilterContext *next; | ||||||
| } AVBitStreamFilterContext; | } AVBitStreamFilterContext; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | typedef struct AVBSFInternal AVBSFInternal; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * The bitstream filter state. | ||||||
|  |  * | ||||||
|  |  * This struct must be allocated with av_bsf_alloc() and freed with | ||||||
|  |  * av_bsf_free(). | ||||||
|  |  * | ||||||
|  |  * The fields in the struct will only be changed (by the caller or by the | ||||||
|  |  * filter) as described in their documentation, and are to be considered | ||||||
|  |  * immutable otherwise. | ||||||
|  |  */ | ||||||
|  | typedef struct AVBSFContext { | ||||||
|  |     /** | ||||||
|  |      * A class for logging and AVOptions | ||||||
|  |      */ | ||||||
|  |     const AVClass *av_class; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * The bitstream filter this context is an instance of. | ||||||
|  |      */ | ||||||
|  |     const struct AVBitStreamFilter *filter; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Opaque libavcodec internal data. Must not be touched by the caller in any | ||||||
|  |      * way. | ||||||
|  |      */ | ||||||
|  |     AVBSFInternal *internal; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Opaque filter-specific private data. If filter->priv_class is non-NULL, | ||||||
|  |      * this is an AVOptions-enabled struct. | ||||||
|  |      */ | ||||||
|  |     void *priv_data; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Parameters of the input stream. Set by the caller before av_bsf_init(). | ||||||
|  |      */ | ||||||
|  |     AVCodecParameters *par_in; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Parameters of the output stream. Set by the filter in av_bsf_init(). | ||||||
|  |      */ | ||||||
|  |     AVCodecParameters *par_out; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * The timebase used for the timestamps of the input packets. Set by the | ||||||
|  |      * caller before av_bsf_init(). | ||||||
|  |      */ | ||||||
|  |     AVRational time_base_in; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * The timebase used for the timestamps of the output packets. Set by the | ||||||
|  |      * filter in av_bsf_init(). | ||||||
|  |      */ | ||||||
|  |     AVRational time_base_out; | ||||||
|  | } AVBSFContext; | ||||||
|  |  | ||||||
| typedef struct AVBitStreamFilter { | typedef struct AVBitStreamFilter { | ||||||
|     const char *name; |     const char *name; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * A list of codec ids supported by the filter, terminated by | ||||||
|  |      * AV_CODEC_ID_NONE. | ||||||
|  |      * May be NULL, in that case the bitstream filter works with any codec id. | ||||||
|  |      */ | ||||||
|  |     const enum AVCodecID *codec_ids; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * A class for the private data, used to declare bitstream filter private | ||||||
|  |      * AVOptions. This field is NULL for bitstream filters that do not declare | ||||||
|  |      * any options. | ||||||
|  |      * | ||||||
|  |      * If this field is non-NULL, the first member of the filter private data | ||||||
|  |      * must be a pointer to AVClass, which will be set by libavcodec generic | ||||||
|  |      * code to this class. | ||||||
|  |      */ | ||||||
|  |     const AVClass *priv_class; | ||||||
|  |  | ||||||
|  |     /***************************************************************** | ||||||
|  |      * No fields below this line are part of the public API. They | ||||||
|  |      * may not be used outside of libavcodec and can be changed and | ||||||
|  |      * removed at will. | ||||||
|  |      * New public fields should be added right above. | ||||||
|  |      ***************************************************************** | ||||||
|  |      */ | ||||||
|  |  | ||||||
|     int priv_data_size; |     int priv_data_size; | ||||||
|     int (*filter)(AVBitStreamFilterContext *bsfc, |     int (*init)(AVBSFContext *ctx); | ||||||
|                   AVCodecContext *avctx, const char *args, |     int (*filter)(AVBSFContext *ctx, AVPacket *pkt); | ||||||
|                   uint8_t **poutbuf, int *poutbuf_size, |     void (*close)(AVBSFContext *ctx); | ||||||
|                   const uint8_t *buf, int buf_size, int keyframe); |  | ||||||
|     void (*close)(AVBitStreamFilterContext *bsfc); |  | ||||||
|     struct AVBitStreamFilter *next; |  | ||||||
| } AVBitStreamFilter; | } AVBitStreamFilter; | ||||||
|  |  | ||||||
|  | #if FF_API_OLD_BSF | ||||||
|  | /** | ||||||
|  |  * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext) | ||||||
|  |  * is deprecated. Use the new bitstream filtering API (using AVBSFContext). | ||||||
|  |  */ | ||||||
|  | attribute_deprecated | ||||||
| void av_register_bitstream_filter(AVBitStreamFilter *bsf); | void av_register_bitstream_filter(AVBitStreamFilter *bsf); | ||||||
|  | attribute_deprecated | ||||||
| AVBitStreamFilterContext *av_bitstream_filter_init(const char *name); | AVBitStreamFilterContext *av_bitstream_filter_init(const char *name); | ||||||
|  | attribute_deprecated | ||||||
| int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc, | int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc, | ||||||
|                                AVCodecContext *avctx, const char *args, |                                AVCodecContext *avctx, const char *args, | ||||||
|                                uint8_t **poutbuf, int *poutbuf_size, |                                uint8_t **poutbuf, int *poutbuf_size, | ||||||
|                                const uint8_t *buf, int buf_size, int keyframe); |                                const uint8_t *buf, int buf_size, int keyframe); | ||||||
|  | attribute_deprecated | ||||||
| void av_bitstream_filter_close(AVBitStreamFilterContext *bsf); | void av_bitstream_filter_close(AVBitStreamFilterContext *bsf); | ||||||
|  | attribute_deprecated | ||||||
| AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f); | AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @return a bitstream filter with the specified name or NULL if no such | ||||||
|  |  *         bitstream filter exists. | ||||||
|  |  */ | ||||||
|  | const AVBitStreamFilter *av_bsf_get_by_name(const char *name); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Iterate over all registered bitstream filters. | ||||||
|  |  * | ||||||
|  |  * @param opaque a pointer where libavcodec will store the iteration state. Must | ||||||
|  |  *               point to NULL to start the iteration. | ||||||
|  |  * | ||||||
|  |  * @return the next registered bitstream filter or NULL when the iteration is | ||||||
|  |  *         finished | ||||||
|  |  */ | ||||||
|  | const AVBitStreamFilter *av_bsf_next(void **opaque); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Allocate a context for a given bitstream filter. The caller must fill in the | ||||||
|  |  * context parameters as described in the documentation and then call | ||||||
|  |  * av_bsf_init() before sending any data to the filter. | ||||||
|  |  * | ||||||
|  |  * @param filter the filter for which to allocate an instance. | ||||||
|  |  * @param ctx a pointer into which the pointer to the newly-allocated context | ||||||
|  |  *            will be written. It must be freed with av_bsf_free() after the | ||||||
|  |  *            filtering is done. | ||||||
|  |  * | ||||||
|  |  * @return 0 on success, a negative AVERROR code on failure | ||||||
|  |  */ | ||||||
|  | int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **ctx); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Prepare the filter for use, after all the parameters and options have been | ||||||
|  |  * set. | ||||||
|  |  */ | ||||||
|  | int av_bsf_init(AVBSFContext *ctx); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Submit a packet for filtering. | ||||||
|  |  * | ||||||
|  |  * After sending each packet, the filter must be completely drained by calling | ||||||
|  |  * av_bsf_receive_packet() repeatedly until it returns AVERROR(EAGAIN) or | ||||||
|  |  * AVERROR_EOF. | ||||||
|  |  * | ||||||
|  |  * @param pkt the packet to filter. The bitstream filter will take ownership of | ||||||
|  |  * the packet and reset the contents of pkt. pkt is not touched if an error occurs. | ||||||
|  |  * This parameter may be NULL, which signals the end of the stream (i.e. no more | ||||||
|  |  * packets will be sent). That will cause the filter to output any packets it | ||||||
|  |  * may have buffered internally. | ||||||
|  |  * | ||||||
|  |  * @return 0 on success, a negative AVERROR on error. | ||||||
|  |  */ | ||||||
|  | int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Retrieve a filtered packet. | ||||||
|  |  * | ||||||
|  |  * @param[out] pkt this struct will be filled with the contents of the filtered | ||||||
|  |  *                 packet. It is owned by the caller and must be freed using | ||||||
|  |  *                 av_packet_unref() when it is no longer needed. | ||||||
|  |  *                 This parameter should be "clean" (i.e. freshly allocated | ||||||
|  |  *                 with av_packet_alloc() or unreffed with av_packet_unref()) | ||||||
|  |  *                 when this function is called. If this function returns | ||||||
|  |  *                 successfully, the contents of pkt will be completely | ||||||
|  |  *                 overwritten by the returned data. On failure, pkt is not | ||||||
|  |  *                 touched. | ||||||
|  |  * | ||||||
|  |  * @return 0 on success. AVERROR(EAGAIN) if more packets need to be sent to the | ||||||
|  |  * filter (using av_bsf_send_packet()) to get more output. AVERROR_EOF if there | ||||||
|  |  * will be no further output from the filter. Another negative AVERROR value if | ||||||
|  |  * an error occurs. | ||||||
|  |  * | ||||||
|  |  * @note one input packet may result in several output packets, so after sending | ||||||
|  |  * a packet with av_bsf_send_packet(), this function needs to be called | ||||||
|  |  * repeatedly until it stops returning 0. It is also possible for a filter to | ||||||
|  |  * output fewer packets than were sent to it, so this function may return | ||||||
|  |  * AVERROR(EAGAIN) immediately after a successful av_bsf_send_packet() call. | ||||||
|  |  */ | ||||||
|  | int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Free a bitstream filter context and everything associated with it; write NULL | ||||||
|  |  * into the supplied pointer. | ||||||
|  |  */ | ||||||
|  | void av_bsf_free(AVBSFContext **ctx); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Get the AVClass for AVBSFContext. It can be used in combination with | ||||||
|  |  * AV_OPT_SEARCH_FAKE_OBJ for examining options. | ||||||
|  |  * | ||||||
|  |  * @see av_opt_find(). | ||||||
|  |  */ | ||||||
|  | const AVClass *av_bsf_get_class(void); | ||||||
|  |  | ||||||
| /* memory */ | /* memory */ | ||||||
|  |  | ||||||
|   | |||||||
| @@ -21,56 +21,70 @@ | |||||||
| #include <string.h> | #include <string.h> | ||||||
|  |  | ||||||
| #include "avcodec.h" | #include "avcodec.h" | ||||||
|  |  | ||||||
|  | #include "libavutil/internal.h" | ||||||
| #include "libavutil/mem.h" | #include "libavutil/mem.h" | ||||||
|  |  | ||||||
| static AVBitStreamFilter *first_bitstream_filter = NULL; | #if FF_API_OLD_BSF | ||||||
|  | FF_DISABLE_DEPRECATION_WARNINGS | ||||||
|  |  | ||||||
| AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f) | AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f) | ||||||
| { | { | ||||||
|     if (f) |     const AVBitStreamFilter *filter = NULL; | ||||||
|         return f->next; |     void *opaque = NULL; | ||||||
|     else |  | ||||||
|         return first_bitstream_filter; |     while (filter != f) | ||||||
|  |         filter = av_bsf_next(&opaque); | ||||||
|  |  | ||||||
|  |     return av_bsf_next(&opaque); | ||||||
| } | } | ||||||
|  |  | ||||||
| void av_register_bitstream_filter(AVBitStreamFilter *bsf) | void av_register_bitstream_filter(AVBitStreamFilter *bsf) | ||||||
| { | { | ||||||
|     bsf->next              = first_bitstream_filter; |  | ||||||
|     first_bitstream_filter = bsf; |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | typedef struct BSFCompatContext { | ||||||
|  |     AVBSFContext *ctx; | ||||||
|  | } BSFCompatContext; | ||||||
|  |  | ||||||
| AVBitStreamFilterContext *av_bitstream_filter_init(const char *name) | AVBitStreamFilterContext *av_bitstream_filter_init(const char *name) | ||||||
| { | { | ||||||
|     AVBitStreamFilter *bsf = first_bitstream_filter; |     AVBitStreamFilterContext *ctx = NULL; | ||||||
|  |     BSFCompatContext         *priv = NULL; | ||||||
|  |     const AVBitStreamFilter *bsf; | ||||||
|  |  | ||||||
|     while (bsf) { |     bsf = av_bsf_get_by_name(name); | ||||||
|         if (!strcmp(name, bsf->name)) { |     if (!bsf) | ||||||
|             AVBitStreamFilterContext *bsfc = |         return NULL; | ||||||
|                 av_mallocz(sizeof(AVBitStreamFilterContext)); |  | ||||||
|             if (!bsfc) |     ctx = av_mallocz(sizeof(*ctx)); | ||||||
|                 return NULL; |     if (!ctx) | ||||||
|             bsfc->filter    = bsf; |         return NULL; | ||||||
|             bsfc->priv_data = NULL; |  | ||||||
|             if (bsf->priv_data_size) { |     priv = av_mallocz(sizeof(*priv)); | ||||||
|                 bsfc->priv_data = av_mallocz(bsf->priv_data_size); |     if (!priv) | ||||||
|                 if (!bsfc->priv_data) { |         goto fail; | ||||||
|                     av_freep(&bsfc); |  | ||||||
|                     return NULL; |  | ||||||
|                 } |     ctx->filter    = bsf; | ||||||
|             } |     ctx->priv_data = priv; | ||||||
|             return bsfc; |  | ||||||
|         } |     return ctx; | ||||||
|         bsf = bsf->next; |  | ||||||
|     } | fail: | ||||||
|  |     if (priv) | ||||||
|  |         av_bsf_free(&priv->ctx); | ||||||
|  |     av_freep(&priv); | ||||||
|  |     av_freep(&ctx); | ||||||
|     return NULL; |     return NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| void av_bitstream_filter_close(AVBitStreamFilterContext *bsfc) | void av_bitstream_filter_close(AVBitStreamFilterContext *bsfc) | ||||||
| { | { | ||||||
|     if (bsfc->filter->close) |     BSFCompatContext *priv = bsfc->priv_data; | ||||||
|         bsfc->filter->close(bsfc); |  | ||||||
|  |     av_bsf_free(&priv->ctx); | ||||||
|     av_freep(&bsfc->priv_data); |     av_freep(&bsfc->priv_data); | ||||||
|     av_parser_close(bsfc->parser); |  | ||||||
|     av_free(bsfc); |     av_free(bsfc); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -79,8 +93,71 @@ int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc, | |||||||
|                                uint8_t **poutbuf, int *poutbuf_size, |                                uint8_t **poutbuf, int *poutbuf_size, | ||||||
|                                const uint8_t *buf, int buf_size, int keyframe) |                                const uint8_t *buf, int buf_size, int keyframe) | ||||||
| { | { | ||||||
|     *poutbuf      = (uint8_t *)buf; |     BSFCompatContext *priv = bsfc->priv_data; | ||||||
|     *poutbuf_size = buf_size; |     AVPacket pkt = { 0 }; | ||||||
|     return bsfc->filter->filter(bsfc, avctx, args, poutbuf, poutbuf_size, |     int ret; | ||||||
|                                 buf, buf_size, keyframe); |  | ||||||
|  |     if (!priv->ctx) { | ||||||
|  |         ret = av_bsf_alloc(bsfc->filter, &priv->ctx); | ||||||
|  |         if (ret < 0) | ||||||
|  |             return ret; | ||||||
|  |  | ||||||
|  |         ret = avcodec_parameters_from_context(priv->ctx->par_in, avctx); | ||||||
|  |         if (ret < 0) | ||||||
|  |             return ret; | ||||||
|  |  | ||||||
|  |         priv->ctx->time_base_in = avctx->time_base; | ||||||
|  |  | ||||||
|  |         ret = av_bsf_init(priv->ctx); | ||||||
|  |         if (ret < 0) | ||||||
|  |             return ret; | ||||||
|  |  | ||||||
|  |         if (priv->ctx->par_out->extradata_size) { | ||||||
|  |             av_freep(&avctx->extradata); | ||||||
|  |             avctx->extradata_size = 0; | ||||||
|  |             avctx->extradata = av_mallocz(priv->ctx->par_out->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); | ||||||
|  |             if (!avctx->extradata) | ||||||
|  |                 return AVERROR(ENOMEM); | ||||||
|  |             memcpy(avctx->extradata, priv->ctx->par_out->extradata, | ||||||
|  |                    priv->ctx->par_out->extradata_size); | ||||||
|  |             avctx->extradata_size = priv->ctx->par_out->extradata_size; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     pkt.data = buf; | ||||||
|  |     pkt.size = buf_size; | ||||||
|  |  | ||||||
|  |     ret = av_bsf_send_packet(priv->ctx, &pkt); | ||||||
|  |     if (ret < 0) | ||||||
|  |         return ret; | ||||||
|  |  | ||||||
|  |     *poutbuf      = NULL; | ||||||
|  |     *poutbuf_size = 0; | ||||||
|  |  | ||||||
|  |     ret = av_bsf_receive_packet(priv->ctx, &pkt); | ||||||
|  |     if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) | ||||||
|  |         return 0; | ||||||
|  |     else if (ret < 0) | ||||||
|  |         return ret; | ||||||
|  |  | ||||||
|  |     *poutbuf = av_malloc(pkt.size + AV_INPUT_BUFFER_PADDING_SIZE); | ||||||
|  |     if (!*poutbuf) { | ||||||
|  |         av_packet_unref(&pkt); | ||||||
|  |         return AVERROR(ENOMEM); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     *poutbuf_size = pkt.size; | ||||||
|  |     memcpy(*poutbuf, pkt.data, pkt.size); | ||||||
|  |  | ||||||
|  |     av_packet_unref(&pkt); | ||||||
|  |  | ||||||
|  |     /* drain all the remaining packets we cannot return */ | ||||||
|  |     while (ret >= 0) { | ||||||
|  |         ret = av_bsf_receive_packet(priv->ctx, &pkt); | ||||||
|  |         av_packet_unref(&pkt); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return 1; | ||||||
| } | } | ||||||
|  | FF_ENABLE_DEPRECATION_WARNINGS | ||||||
|  | #endif | ||||||
|   | |||||||
							
								
								
									
										121
									
								
								libavcodec/bitstream_filters.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								libavcodec/bitstream_filters.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,121 @@ | |||||||
|  | /* | ||||||
|  |  * This file is part of Libav. | ||||||
|  |  * | ||||||
|  |  * Libav is free software; you can redistribute it and/or | ||||||
|  |  * modify it under the terms of the GNU Lesser General Public | ||||||
|  |  * License as published by the Free Software Foundation; either | ||||||
|  |  * version 2.1 of the License, or (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * Libav is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||||
|  |  * Lesser General Public License for more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU Lesser General Public | ||||||
|  |  * License along with Libav; if not, write to the Free Software | ||||||
|  |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include "config.h" | ||||||
|  |  | ||||||
|  | #include "libavutil/common.h" | ||||||
|  | #include "libavutil/log.h" | ||||||
|  |  | ||||||
|  | #include "avcodec.h" | ||||||
|  | #include "bsf.h" | ||||||
|  |  | ||||||
|  | extern const AVBitStreamFilter ff_aac_adtstoasc_bsf; | ||||||
|  | extern const AVBitStreamFilter ff_chomp_bsf; | ||||||
|  | extern const AVBitStreamFilter ff_dump_extradata_bsf; | ||||||
|  | extern const AVBitStreamFilter ff_h264_mp4toannexb_bsf; | ||||||
|  | extern const AVBitStreamFilter ff_hevc_mp4toannexb_bsf; | ||||||
|  | extern const AVBitStreamFilter ff_imx_dump_header_bsf; | ||||||
|  | extern const AVBitStreamFilter ff_mjpeg2jpeg_bsf; | ||||||
|  | extern const AVBitStreamFilter ff_mjpega_dump_header_bsf; | ||||||
|  | extern const AVBitStreamFilter ff_mov2textsub_bsf; | ||||||
|  | extern const AVBitStreamFilter ff_text2movsub_bsf; | ||||||
|  | extern const AVBitStreamFilter ff_noise_bsf; | ||||||
|  | extern const AVBitStreamFilter ff_remove_extradata_bsf; | ||||||
|  |  | ||||||
|  | static const AVBitStreamFilter *bitstream_filters[] = { | ||||||
|  | #if CONFIG_AAC_ADTSTOASC_BSF | ||||||
|  |     &ff_aac_adtstoasc_bsf, | ||||||
|  | #endif | ||||||
|  | #if CONFIG_CHOMP_BSF | ||||||
|  |     &ff_chomp_bsf, | ||||||
|  | #endif | ||||||
|  | #if CONFIG_DUMP_EXTRADATA_BSF | ||||||
|  |     &ff_dump_extradata_bsf, | ||||||
|  | #endif | ||||||
|  | #if CONFIG_H264_MP4TOANNEXB_BSF | ||||||
|  |     &ff_h264_mp4toannexb_bsf, | ||||||
|  | #endif | ||||||
|  | #if CONFIG_HEVC_MP4TOANNEXB_BSF | ||||||
|  |     &ff_hevc_mp4toannexb_bsf, | ||||||
|  | #endif | ||||||
|  | #if CONFIG_IMX_DUMP_HEADER_BSF | ||||||
|  |     &ff_imx_dump_header_bsf, | ||||||
|  | #endif | ||||||
|  | #if CONFIG_MJPEG2JPEG_BSF | ||||||
|  |     &ff_mjpeg2jpeg_bsf, | ||||||
|  | #endif | ||||||
|  | #if CONFIG_MJPEGA_DUMP_HEADER_BSF | ||||||
|  |     &ff_mjpeg2jpeg_bsf, | ||||||
|  | #endif | ||||||
|  | #if CONFIG_MOV2TEXTSUB_BSF | ||||||
|  |     &ff_mov2textsub_bsf, | ||||||
|  | #endif | ||||||
|  | #if CONFIG_TEXT2MOVSUB_BSF | ||||||
|  |     &ff_text2movsub_bsf, | ||||||
|  | #endif | ||||||
|  | #if CONFIG_NOISE_BSF | ||||||
|  |     &ff_noise_bsf, | ||||||
|  | #endif | ||||||
|  | #if CONFIG_REMOVE_EXTRADATA_BSF | ||||||
|  |     &ff_remove_extradata_bsf, | ||||||
|  | #endif | ||||||
|  |     NULL, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const AVBitStreamFilter *av_bsf_next(void **opaque) | ||||||
|  | { | ||||||
|  |     uintptr_t i = (uintptr_t)*opaque; | ||||||
|  |     const AVBitStreamFilter *f = bitstream_filters[i]; | ||||||
|  |  | ||||||
|  |     if (f) | ||||||
|  |         *opaque = (void*)(i + 1); | ||||||
|  |  | ||||||
|  |     return f; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const AVBitStreamFilter *av_bsf_get_by_name(const char *name) | ||||||
|  | { | ||||||
|  |     int i; | ||||||
|  |  | ||||||
|  |     for (i = 0; bitstream_filters[i]; i++) { | ||||||
|  |         const AVBitStreamFilter *f = bitstream_filters[i]; | ||||||
|  |         if (!strcmp(f->name, name)) | ||||||
|  |             return f; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const AVClass *ff_bsf_child_class_next(const AVClass *prev) | ||||||
|  | { | ||||||
|  |     int i; | ||||||
|  |  | ||||||
|  |     /* find the filter that corresponds to prev */ | ||||||
|  |     for (i = 0; prev && bitstream_filters[i]; i++) { | ||||||
|  |         if (bitstream_filters[i]->priv_class == prev) { | ||||||
|  |             i++; | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* find next filter with priv options */ | ||||||
|  |     for (; bitstream_filters[i]; i++) | ||||||
|  |         if (bitstream_filters[i]->priv_class) | ||||||
|  |             return bitstream_filters[i]->priv_class; | ||||||
|  |     return NULL; | ||||||
|  | } | ||||||
							
								
								
									
										219
									
								
								libavcodec/bsf.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										219
									
								
								libavcodec/bsf.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,219 @@ | |||||||
|  | /* | ||||||
|  |  * This file is part of Libav. | ||||||
|  |  * | ||||||
|  |  * Libav is free software; you can redistribute it and/or | ||||||
|  |  * modify it under the terms of the GNU Lesser General Public | ||||||
|  |  * License as published by the Free Software Foundation; either | ||||||
|  |  * version 2.1 of the License, or (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * Libav is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||||
|  |  * Lesser General Public License for more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU Lesser General Public | ||||||
|  |  * License along with Libav; if not, write to the Free Software | ||||||
|  |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | #include "libavutil/log.h" | ||||||
|  | #include "libavutil/mem.h" | ||||||
|  | #include "libavutil/opt.h" | ||||||
|  |  | ||||||
|  | #include "avcodec.h" | ||||||
|  | #include "bsf.h" | ||||||
|  |  | ||||||
|  | struct AVBSFInternal { | ||||||
|  |     AVPacket *buffer_pkt; | ||||||
|  |     int eof; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | void av_bsf_free(AVBSFContext **pctx) | ||||||
|  | { | ||||||
|  |     AVBSFContext *ctx; | ||||||
|  |  | ||||||
|  |     if (!pctx || !*pctx) | ||||||
|  |         return; | ||||||
|  |     ctx = *pctx; | ||||||
|  |  | ||||||
|  |     if (ctx->filter->close) | ||||||
|  |         ctx->filter->close(ctx); | ||||||
|  |     if (ctx->filter->priv_class && ctx->priv_data) | ||||||
|  |         av_opt_free(ctx->priv_data); | ||||||
|  |  | ||||||
|  |     av_opt_free(ctx); | ||||||
|  |  | ||||||
|  |     av_packet_free(&ctx->internal->buffer_pkt); | ||||||
|  |     av_freep(&ctx->internal); | ||||||
|  |     av_freep(&ctx->priv_data); | ||||||
|  |  | ||||||
|  |     avcodec_parameters_free(&ctx->par_in); | ||||||
|  |     avcodec_parameters_free(&ctx->par_out); | ||||||
|  |  | ||||||
|  |     av_freep(pctx); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void *bsf_child_next(void *obj, void *prev) | ||||||
|  | { | ||||||
|  |     AVBSFContext *ctx = obj; | ||||||
|  |     if (!prev && ctx->filter->priv_class) | ||||||
|  |         return ctx->priv_data; | ||||||
|  |     return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static const AVClass bsf_class = { | ||||||
|  |     .class_name       = "AVBSFContext", | ||||||
|  |     .item_name        = av_default_item_name, | ||||||
|  |     .version          = LIBAVUTIL_VERSION_INT, | ||||||
|  |     .child_next       = bsf_child_next, | ||||||
|  |     .child_class_next = ff_bsf_child_class_next, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const AVClass *av_bsf_get_class(void) | ||||||
|  | { | ||||||
|  |     return &bsf_class; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **pctx) | ||||||
|  | { | ||||||
|  |     AVBSFContext *ctx; | ||||||
|  |     int ret; | ||||||
|  |  | ||||||
|  |     ctx = av_mallocz(sizeof(*ctx)); | ||||||
|  |     if (!ctx) | ||||||
|  |         return AVERROR(ENOMEM); | ||||||
|  |  | ||||||
|  |     ctx->av_class = &bsf_class; | ||||||
|  |     ctx->filter   = filter; | ||||||
|  |  | ||||||
|  |     ctx->par_in  = avcodec_parameters_alloc(); | ||||||
|  |     ctx->par_out = avcodec_parameters_alloc(); | ||||||
|  |     if (!ctx->par_in || !ctx->par_out) { | ||||||
|  |         ret = AVERROR(ENOMEM); | ||||||
|  |         goto fail; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ctx->internal = av_mallocz(sizeof(*ctx->internal)); | ||||||
|  |     if (!ctx->internal) { | ||||||
|  |         ret = AVERROR(ENOMEM); | ||||||
|  |         goto fail; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ctx->internal->buffer_pkt = av_packet_alloc(); | ||||||
|  |     if (!ctx->internal->buffer_pkt) { | ||||||
|  |         ret = AVERROR(ENOMEM); | ||||||
|  |         goto fail; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     av_opt_set_defaults(ctx); | ||||||
|  |  | ||||||
|  |     /* allocate priv data and init private options */ | ||||||
|  |     if (filter->priv_data_size) { | ||||||
|  |         ctx->priv_data = av_mallocz(filter->priv_data_size); | ||||||
|  |         if (!ctx->priv_data) { | ||||||
|  |             ret = AVERROR(ENOMEM); | ||||||
|  |             goto fail; | ||||||
|  |         } | ||||||
|  |         if (filter->priv_class) { | ||||||
|  |             *(const AVClass **)ctx->priv_data = filter->priv_class; | ||||||
|  |             av_opt_set_defaults(ctx->priv_data); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     *pctx = ctx; | ||||||
|  |     return 0; | ||||||
|  | fail: | ||||||
|  |     av_bsf_free(&ctx); | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int av_bsf_init(AVBSFContext *ctx) | ||||||
|  | { | ||||||
|  |     int ret, i; | ||||||
|  |  | ||||||
|  |     /* check that the codec is supported */ | ||||||
|  |     if (ctx->filter->codec_ids) { | ||||||
|  |         for (i = 0; ctx->filter->codec_ids[i] != AV_CODEC_ID_NONE; i++) | ||||||
|  |             if (ctx->par_in->codec_id == ctx->filter->codec_ids[i]) | ||||||
|  |                 break; | ||||||
|  |         if (ctx->filter->codec_ids[i] == AV_CODEC_ID_NONE) { | ||||||
|  |             const AVCodecDescriptor *desc = avcodec_descriptor_get(ctx->par_in->codec_id); | ||||||
|  |             av_log(ctx, AV_LOG_ERROR, "Codec '%s' (%d) is not supported by the " | ||||||
|  |                    "bitstream filter '%s'. Supported codecs are: ", | ||||||
|  |                    desc ? desc->name : "unknown", ctx->par_in->codec_id, ctx->filter->name); | ||||||
|  |             for (i = 0; ctx->filter->codec_ids[i] != AV_CODEC_ID_NONE; i++) { | ||||||
|  |                 desc = avcodec_descriptor_get(ctx->filter->codec_ids[i]); | ||||||
|  |                 av_log(ctx, AV_LOG_ERROR, "%s (%d) ", | ||||||
|  |                        desc ? desc->name : "unknown", ctx->filter->codec_ids[i]); | ||||||
|  |             } | ||||||
|  |             av_log(ctx, AV_LOG_ERROR, "\n"); | ||||||
|  |             return AVERROR(EINVAL); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* initialize output parameters to be the same as input | ||||||
|  |      * init below might overwrite that */ | ||||||
|  |     ret = avcodec_parameters_copy(ctx->par_out, ctx->par_in); | ||||||
|  |     if (ret < 0) | ||||||
|  |         return ret; | ||||||
|  |  | ||||||
|  |     ctx->time_base_out = ctx->time_base_in; | ||||||
|  |  | ||||||
|  |     if (ctx->filter->init) { | ||||||
|  |         ret = ctx->filter->init(ctx); | ||||||
|  |         if (ret < 0) | ||||||
|  |             return ret; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt) | ||||||
|  | { | ||||||
|  |     if (!pkt || !pkt->data) { | ||||||
|  |         ctx->internal->eof = 1; | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (ctx->internal->eof) { | ||||||
|  |         av_log(ctx, AV_LOG_ERROR, "A non-NULL packet sent after an EOF.\n"); | ||||||
|  |         return AVERROR(EINVAL); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (ctx->internal->buffer_pkt->data || | ||||||
|  |         ctx->internal->buffer_pkt->side_data_elems) | ||||||
|  |         return AVERROR(EAGAIN); | ||||||
|  |  | ||||||
|  |     av_packet_move_ref(ctx->internal->buffer_pkt, pkt); | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt) | ||||||
|  | { | ||||||
|  |     return ctx->filter->filter(ctx, pkt); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt) | ||||||
|  | { | ||||||
|  |     AVBSFInternal *in = ctx->internal; | ||||||
|  |     AVPacket *tmp_pkt; | ||||||
|  |  | ||||||
|  |     if (in->eof) | ||||||
|  |         return AVERROR_EOF; | ||||||
|  |  | ||||||
|  |     if (!ctx->internal->buffer_pkt->data && | ||||||
|  |         !ctx->internal->buffer_pkt->side_data_elems) | ||||||
|  |         return AVERROR(EAGAIN); | ||||||
|  |  | ||||||
|  |     tmp_pkt = av_packet_alloc(); | ||||||
|  |     if (!tmp_pkt) | ||||||
|  |         return AVERROR(ENOMEM); | ||||||
|  |  | ||||||
|  |     *pkt = ctx->internal->buffer_pkt; | ||||||
|  |     ctx->internal->buffer_pkt = tmp_pkt; | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
							
								
								
									
										33
									
								
								libavcodec/bsf.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								libavcodec/bsf.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | /* | ||||||
|  |  * This file is part of Libav. | ||||||
|  |  * | ||||||
|  |  * Libav is free software; you can redistribute it and/or | ||||||
|  |  * modify it under the terms of the GNU Lesser General Public | ||||||
|  |  * License as published by the Free Software Foundation; either | ||||||
|  |  * version 2.1 of the License, or (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * Libav is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||||
|  |  * Lesser General Public License for more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU Lesser General Public | ||||||
|  |  * License along with Libav; if not, write to the Free Software | ||||||
|  |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef AVCODEC_BSF_H | ||||||
|  | #define AVCODEC_BSF_H | ||||||
|  |  | ||||||
|  | #include "avcodec.h" | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Called by the biststream filters to get the next packet for filtering. | ||||||
|  |  * The filter is responsible for either freeing the packet or passing it to the | ||||||
|  |  * caller. | ||||||
|  |  */ | ||||||
|  | int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt); | ||||||
|  |  | ||||||
|  | const AVClass *ff_bsf_child_class_next(const AVClass *prev); | ||||||
|  |  | ||||||
|  | #endif /* AVCODEC_BSF_H */ | ||||||
| @@ -20,19 +20,23 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include "avcodec.h" | #include "avcodec.h" | ||||||
|  | #include "bsf.h" | ||||||
| #include "internal.h" | #include "internal.h" | ||||||
|  |  | ||||||
| static int chomp_filter(AVBitStreamFilterContext *bsfc, | static int chomp_filter(AVBSFContext *ctx, AVPacket *out) | ||||||
|                         AVCodecContext *avctx, const char *args, |  | ||||||
|                         uint8_t  **poutbuf, int *poutbuf_size, |  | ||||||
|                         const uint8_t *buf, int      buf_size, |  | ||||||
|                         int keyframe) |  | ||||||
| { | { | ||||||
|     while (buf_size > 0 && !buf[buf_size-1]) |     AVPacket *in; | ||||||
|         buf_size--; |     int ret; | ||||||
|  |  | ||||||
|     *poutbuf = (uint8_t*) buf; |     ret = ff_bsf_get_packet(ctx, &in); | ||||||
|     *poutbuf_size = buf_size; |     if (ret < 0) | ||||||
|  |         return ret; | ||||||
|  |  | ||||||
|  |     while (in->size > 0 && !in->data[in->size - 1]) | ||||||
|  |         in->size--; | ||||||
|  |  | ||||||
|  |     av_packet_move_ref(out, in); | ||||||
|  |     av_packet_free(&in); | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| @@ -40,8 +44,7 @@ static int chomp_filter(AVBitStreamFilterContext *bsfc, | |||||||
| /** | /** | ||||||
|  * This filter removes a string of NULL bytes from the end of a packet. |  * This filter removes a string of NULL bytes from the end of a packet. | ||||||
|  */ |  */ | ||||||
| AVBitStreamFilter ff_chomp_bsf = { | const AVBitStreamFilter ff_chomp_bsf = { | ||||||
|     "chomp", |     .name   = "chomp", | ||||||
|     0, |     .filter = chomp_filter, | ||||||
|     chomp_filter, |  | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -21,35 +21,81 @@ | |||||||
| #include <string.h> | #include <string.h> | ||||||
|  |  | ||||||
| #include "avcodec.h" | #include "avcodec.h" | ||||||
|  | #include "bsf.h" | ||||||
|  |  | ||||||
|  | #include "libavutil/log.h" | ||||||
| #include "libavutil/mem.h" | #include "libavutil/mem.h" | ||||||
|  | #include "libavutil/opt.h" | ||||||
|  |  | ||||||
|  | enum DumpFreq { | ||||||
|  |     DUMP_FREQ_KEYFRAME, | ||||||
|  |     DUMP_FREQ_ALL, | ||||||
|  | }; | ||||||
|  |  | ||||||
| static int dump_extradata(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, | typedef struct DumpExtradataContext { | ||||||
|                      uint8_t **poutbuf, int *poutbuf_size, |     const AVClass *class; | ||||||
|                      const uint8_t *buf, int buf_size, int keyframe){ |     int freq; | ||||||
|     int cmd= args ? *args : 0; | } DumpExtradataContext; | ||||||
|     /* cast to avoid warning about discarding qualifiers */ |  | ||||||
|     if(avctx->extradata){ |  | ||||||
|         if(  (keyframe && (avctx->flags2 & AV_CODEC_FLAG2_LOCAL_HEADER) && cmd == 'a') |  | ||||||
|            ||(keyframe && (cmd=='k' || !cmd)) |  | ||||||
|            ||(cmd=='e') |  | ||||||
|             /*||(? && (s->flags & PARSER_FLAG_DUMP_EXTRADATA_AT_BEGIN)*/){ |  | ||||||
|             int size= buf_size + avctx->extradata_size; |  | ||||||
|             *poutbuf_size= size; |  | ||||||
|             *poutbuf= av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE); |  | ||||||
|             if (!*poutbuf) |  | ||||||
|                 return AVERROR(ENOMEM); |  | ||||||
|  |  | ||||||
|             memcpy(*poutbuf, avctx->extradata, avctx->extradata_size); | static int dump_extradata(AVBSFContext *ctx, AVPacket *out) | ||||||
|             memcpy((*poutbuf) + avctx->extradata_size, buf, buf_size + AV_INPUT_BUFFER_PADDING_SIZE); | { | ||||||
|             return 1; |     DumpExtradataContext *s = ctx->priv_data; | ||||||
|  |     AVPacket *in; | ||||||
|  |     int ret = 0; | ||||||
|  |  | ||||||
|  |     ret = ff_bsf_get_packet(ctx, &in); | ||||||
|  |     if (ret < 0) | ||||||
|  |         return ret; | ||||||
|  |  | ||||||
|  |     if (ctx->par_in->extradata && | ||||||
|  |         (s->freq == DUMP_FREQ_ALL || | ||||||
|  |          (s->freq == DUMP_FREQ_KEYFRAME && in->flags & AV_PKT_FLAG_KEY))) { | ||||||
|  |         if (in->size >= INT_MAX - ctx->par_in->extradata_size) { | ||||||
|  |             ret = AVERROR(ERANGE); | ||||||
|  |             goto fail; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         ret = av_new_packet(out, in->size + ctx->par_in->extradata_size); | ||||||
|  |         if (ret < 0) | ||||||
|  |             goto fail; | ||||||
|  |  | ||||||
|  |         ret = av_packet_copy_props(out, in); | ||||||
|  |         if (ret < 0) { | ||||||
|  |             av_packet_unref(out); | ||||||
|  |             goto fail; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         memcpy(out->data, ctx->par_in->extradata, ctx->par_in->extradata_size); | ||||||
|  |         memcpy(out->data + ctx->par_in->extradata_size, in->data, in->size); | ||||||
|  |     } else { | ||||||
|  |         av_packet_move_ref(out, in); | ||||||
|     } |     } | ||||||
|     return 0; |  | ||||||
|  | fail: | ||||||
|  |     av_packet_free(&in); | ||||||
|  |  | ||||||
|  |     return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| AVBitStreamFilter ff_dump_extradata_bsf={ | #define OFFSET(x) offsetof(DumpExtradataContext, x) | ||||||
|     "dump_extra", | static const AVOption options[] = { | ||||||
|     0, |     { "freq", "When do dump extradata", OFFSET(freq), AV_OPT_TYPE_INT, | ||||||
|     dump_extradata, |         { .i64 = DUMP_FREQ_KEYFRAME }, DUMP_FREQ_KEYFRAME, DUMP_FREQ_ALL, 0, "freq" }, | ||||||
|  |         { "keyframe", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = DUMP_FREQ_KEYFRAME }, .unit = "freq" }, | ||||||
|  |         { "all",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = DUMP_FREQ_ALL      }, .unit = "freq" }, | ||||||
|  |     { NULL }, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static const AVClass dump_extradata_class = { | ||||||
|  |     .class_name = "dump_extradata bsf", | ||||||
|  |     .item_name  = av_default_item_name, | ||||||
|  |     .option     = options, | ||||||
|  |     .version    = LIBAVUTIL_VERSION_MAJOR, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const AVBitStreamFilter ff_dump_extradata_bsf = { | ||||||
|  |     .name           = "dump_extra", | ||||||
|  |     .priv_data_size = sizeof(DumpExtradataContext), | ||||||
|  |     .priv_class     = &dump_extradata_class, | ||||||
|  |     .filter         = dump_extradata, | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -23,7 +23,9 @@ | |||||||
|  |  | ||||||
| #include "libavutil/intreadwrite.h" | #include "libavutil/intreadwrite.h" | ||||||
| #include "libavutil/mem.h" | #include "libavutil/mem.h" | ||||||
|  |  | ||||||
| #include "avcodec.h" | #include "avcodec.h" | ||||||
|  | #include "bsf.h" | ||||||
|  |  | ||||||
| typedef struct H264BSFContext { | typedef struct H264BSFContext { | ||||||
|     uint8_t  length_size; |     uint8_t  length_size; | ||||||
| @@ -31,41 +33,39 @@ typedef struct H264BSFContext { | |||||||
|     int      extradata_parsed; |     int      extradata_parsed; | ||||||
| } H264BSFContext; | } H264BSFContext; | ||||||
|  |  | ||||||
| static int alloc_and_copy(uint8_t **poutbuf, int *poutbuf_size, | static int alloc_and_copy(AVPacket *out, | ||||||
|                           const uint8_t *sps_pps, uint32_t sps_pps_size, |                           const uint8_t *sps_pps, uint32_t sps_pps_size, | ||||||
|                           const uint8_t *in, uint32_t in_size) |                           const uint8_t *in, uint32_t in_size) | ||||||
| { | { | ||||||
|     uint32_t offset         = *poutbuf_size; |     uint32_t offset         = out->size; | ||||||
|     uint8_t nal_header_size = offset ? 3 : 4; |     uint8_t nal_header_size = offset ? 3 : 4; | ||||||
|     int err; |     int err; | ||||||
|  |  | ||||||
|     *poutbuf_size += sps_pps_size + in_size + nal_header_size; |     err = av_grow_packet(out, sps_pps_size + in_size + nal_header_size); | ||||||
|     if ((err = av_reallocp(poutbuf, |     if (err < 0) | ||||||
|                            *poutbuf_size + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) { |  | ||||||
|         *poutbuf_size = 0; |  | ||||||
|         return err; |         return err; | ||||||
|     } |  | ||||||
|     if (sps_pps) |     if (sps_pps) | ||||||
|         memcpy(*poutbuf + offset, sps_pps, sps_pps_size); |         memcpy(out->data + offset, sps_pps, sps_pps_size); | ||||||
|     memcpy(*poutbuf + sps_pps_size + nal_header_size + offset, in, in_size); |     memcpy(out->data + sps_pps_size + nal_header_size + offset, in, in_size); | ||||||
|     if (!offset) { |     if (!offset) { | ||||||
|         AV_WB32(*poutbuf + sps_pps_size, 1); |         AV_WB32(out->data + sps_pps_size, 1); | ||||||
|     } else { |     } else { | ||||||
|         (*poutbuf + offset + sps_pps_size)[0] = |         (out->data + offset + sps_pps_size)[0] = | ||||||
|         (*poutbuf + offset + sps_pps_size)[1] = 0; |         (out->data + offset + sps_pps_size)[1] = 0; | ||||||
|         (*poutbuf + offset + sps_pps_size)[2] = 1; |         (out->data + offset + sps_pps_size)[2] = 1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int h264_extradata_to_annexb(AVCodecContext *avctx, const int padding) | static int h264_extradata_to_annexb(AVBSFContext *ctx, const int padding) | ||||||
| { | { | ||||||
|     uint16_t unit_size; |     uint16_t unit_size; | ||||||
|     uint64_t total_size                 = 0; |     uint64_t total_size                 = 0; | ||||||
|     uint8_t *out                        = NULL, unit_nb, sps_done = 0, |     uint8_t *out                        = NULL, unit_nb, sps_done = 0, | ||||||
|              sps_seen                   = 0, pps_seen = 0; |              sps_seen                   = 0, pps_seen = 0; | ||||||
|     const uint8_t *extradata            = avctx->extradata + 4; |     const uint8_t *extradata            = ctx->par_in->extradata + 4; | ||||||
|     static const uint8_t nalu_header[4] = { 0, 0, 0, 1 }; |     static const uint8_t nalu_header[4] = { 0, 0, 0, 1 }; | ||||||
|     int length_size = (*extradata++ & 0x3) + 1; // retrieve length coded size |     int length_size = (*extradata++ & 0x3) + 1; // retrieve length coded size | ||||||
|  |  | ||||||
| @@ -90,8 +90,8 @@ static int h264_extradata_to_annexb(AVCodecContext *avctx, const int padding) | |||||||
|         unit_size   = AV_RB16(extradata); |         unit_size   = AV_RB16(extradata); | ||||||
|         total_size += unit_size + 4; |         total_size += unit_size + 4; | ||||||
|         if (total_size > INT_MAX - padding || |         if (total_size > INT_MAX - padding || | ||||||
|             extradata + 2 + unit_size > avctx->extradata + |             extradata + 2 + unit_size > ctx->par_in->extradata + | ||||||
|             avctx->extradata_size) { |             ctx->par_in->extradata_size) { | ||||||
|             av_free(out); |             av_free(out); | ||||||
|             return AVERROR(EINVAL); |             return AVERROR(EINVAL); | ||||||
|         } |         } | ||||||
| @@ -112,100 +112,125 @@ static int h264_extradata_to_annexb(AVCodecContext *avctx, const int padding) | |||||||
|         memset(out + total_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); |         memset(out + total_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); | ||||||
|  |  | ||||||
|     if (!sps_seen) |     if (!sps_seen) | ||||||
|         av_log(avctx, AV_LOG_WARNING, |         av_log(ctx, AV_LOG_WARNING, | ||||||
|                "Warning: SPS NALU missing or invalid. " |                "Warning: SPS NALU missing or invalid. " | ||||||
|                "The resulting stream may not play.\n"); |                "The resulting stream may not play.\n"); | ||||||
|  |  | ||||||
|     if (!pps_seen) |     if (!pps_seen) | ||||||
|         av_log(avctx, AV_LOG_WARNING, |         av_log(ctx, AV_LOG_WARNING, | ||||||
|                "Warning: PPS NALU missing or invalid. " |                "Warning: PPS NALU missing or invalid. " | ||||||
|                "The resulting stream may not play.\n"); |                "The resulting stream may not play.\n"); | ||||||
|  |  | ||||||
|     av_free(avctx->extradata); |     av_freep(&ctx->par_out->extradata); | ||||||
|     avctx->extradata      = out; |     ctx->par_out->extradata      = out; | ||||||
|     avctx->extradata_size = total_size; |     ctx->par_out->extradata_size = total_size; | ||||||
|  |  | ||||||
|     return length_size; |     return length_size; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int h264_mp4toannexb_filter(AVBitStreamFilterContext *bsfc, | static int h264_mp4toannexb_init(AVBSFContext *ctx) | ||||||
|                                    AVCodecContext *avctx, const char *args, |  | ||||||
|                                    uint8_t **poutbuf, int *poutbuf_size, |  | ||||||
|                                    const uint8_t *buf, int buf_size, |  | ||||||
|                                    int keyframe) |  | ||||||
| { | { | ||||||
|     H264BSFContext *ctx = bsfc->priv_data; |     H264BSFContext *s = ctx->priv_data; | ||||||
|  |     int ret; | ||||||
|  |  | ||||||
|  |     /* retrieve sps and pps NAL units from extradata */ | ||||||
|  |     if (ctx->par_in->extradata_size >= 6) { | ||||||
|  |         ret = h264_extradata_to_annexb(ctx, AV_INPUT_BUFFER_PADDING_SIZE); | ||||||
|  |         if (ret < 0) | ||||||
|  |             return ret; | ||||||
|  |  | ||||||
|  |         s->length_size      = ret; | ||||||
|  |         s->first_idr        = 1; | ||||||
|  |         s->extradata_parsed = 1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out) | ||||||
|  | { | ||||||
|  |     H264BSFContext *s = ctx->priv_data; | ||||||
|  |  | ||||||
|  |     AVPacket *in; | ||||||
|     uint8_t unit_type; |     uint8_t unit_type; | ||||||
|     int32_t nal_size; |     int32_t nal_size; | ||||||
|     uint32_t cumul_size    = 0; |     uint32_t cumul_size    = 0; | ||||||
|     const uint8_t *buf_end = buf + buf_size; |     const uint8_t *buf; | ||||||
|  |     const uint8_t *buf_end; | ||||||
|  |     int            buf_size; | ||||||
|     int ret = 0; |     int ret = 0; | ||||||
|  |  | ||||||
|  |     ret = ff_bsf_get_packet(ctx, &in); | ||||||
|  |     if (ret < 0) | ||||||
|  |         return ret; | ||||||
|  |  | ||||||
|     /* nothing to filter */ |     /* nothing to filter */ | ||||||
|     if (!avctx->extradata || avctx->extradata_size < 6) { |     if (!s->extradata_parsed) { | ||||||
|         *poutbuf      = (uint8_t *)buf; |         av_packet_move_ref(out, in); | ||||||
|         *poutbuf_size = buf_size; |         av_packet_free(&in); | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* retrieve sps and pps NAL units from extradata */ |     buf      = in->data; | ||||||
|     if (!ctx->extradata_parsed) { |     buf_size = in->size; | ||||||
|         ret = h264_extradata_to_annexb(avctx, AV_INPUT_BUFFER_PADDING_SIZE); |     buf_end  = in->data + in->size; | ||||||
|         if (ret < 0) |  | ||||||
|             return ret; |  | ||||||
|         ctx->length_size      = ret; |  | ||||||
|         ctx->first_idr        = 1; |  | ||||||
|         ctx->extradata_parsed = 1; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     *poutbuf_size = 0; |  | ||||||
|     *poutbuf      = NULL; |  | ||||||
|     do { |     do { | ||||||
|         if (buf + ctx->length_size > buf_end) |         if (buf + s->length_size > buf_end) | ||||||
|             goto fail; |             goto fail; | ||||||
|  |  | ||||||
|         if (ctx->length_size == 1) { |         if (s->length_size == 1) { | ||||||
|             nal_size = buf[0]; |             nal_size = buf[0]; | ||||||
|         } else if (ctx->length_size == 2) { |         } else if (s->length_size == 2) { | ||||||
|             nal_size = AV_RB16(buf); |             nal_size = AV_RB16(buf); | ||||||
|         } else |         } else | ||||||
|             nal_size = AV_RB32(buf); |             nal_size = AV_RB32(buf); | ||||||
|  |  | ||||||
|         buf      += ctx->length_size; |         buf += s->length_size; | ||||||
|         unit_type = *buf & 0x1f; |         unit_type = *buf & 0x1f; | ||||||
|  |  | ||||||
|         if (buf + nal_size > buf_end || nal_size < 0) |         if (buf + nal_size > buf_end || nal_size < 0) | ||||||
|             goto fail; |             goto fail; | ||||||
|  |  | ||||||
|         /* prepend only to the first type 5 NAL unit of an IDR picture */ |         /* prepend only to the first type 5 NAL unit of an IDR picture */ | ||||||
|         if (ctx->first_idr && unit_type == 5) { |         if (s->first_idr && unit_type == 5) { | ||||||
|             if (alloc_and_copy(poutbuf, poutbuf_size, |             if (alloc_and_copy(out, | ||||||
|                                avctx->extradata, avctx->extradata_size, |                                ctx->par_out->extradata, ctx->par_out->extradata_size, | ||||||
|                                buf, nal_size) < 0) |                                buf, nal_size) < 0) | ||||||
|                 goto fail; |                 goto fail; | ||||||
|             ctx->first_idr = 0; |             s->first_idr = 0; | ||||||
|         } else { |         } else { | ||||||
|             if (alloc_and_copy(poutbuf, poutbuf_size, |             if (alloc_and_copy(out, | ||||||
|                                NULL, 0, buf, nal_size) < 0) |                                NULL, 0, buf, nal_size) < 0) | ||||||
|                 goto fail; |                 goto fail; | ||||||
|             if (!ctx->first_idr && unit_type == 1) |             if (!s->first_idr && unit_type == 1) | ||||||
|                 ctx->first_idr = 1; |                 s->first_idr = 1; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         buf        += nal_size; |         buf        += nal_size; | ||||||
|         cumul_size += nal_size + ctx->length_size; |         cumul_size += nal_size + s->length_size; | ||||||
|     } while (cumul_size < buf_size); |     } while (cumul_size < buf_size); | ||||||
|  |  | ||||||
|     return 1; |     ret = av_packet_copy_props(out, in); | ||||||
|  |     if (ret < 0) | ||||||
|  |         goto fail; | ||||||
|  |  | ||||||
| fail: | fail: | ||||||
|     av_freep(poutbuf); |     if (ret < 0) | ||||||
|     *poutbuf_size = 0; |         av_packet_unref(out); | ||||||
|     return AVERROR(EINVAL); |     av_packet_free(&in); | ||||||
|  |  | ||||||
|  |     return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| AVBitStreamFilter ff_h264_mp4toannexb_bsf = { | static const enum AVCodecID codec_ids[] = { | ||||||
|     "h264_mp4toannexb", |     AV_CODEC_ID_H264, AV_CODEC_ID_NONE, | ||||||
|     sizeof(H264BSFContext), | }; | ||||||
|     h264_mp4toannexb_filter, |  | ||||||
|  | const AVBitStreamFilter ff_h264_mp4toannexb_bsf = { | ||||||
|  |     .name           = "h264_mp4toannexb", | ||||||
|  |     .priv_data_size = sizeof(H264BSFContext), | ||||||
|  |     .init           = h264_mp4toannexb_init, | ||||||
|  |     .filter         = h264_mp4toannexb_filter, | ||||||
|  |     .codec_ids      = codec_ids, | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -25,6 +25,7 @@ | |||||||
| #include "libavutil/mem.h" | #include "libavutil/mem.h" | ||||||
|  |  | ||||||
| #include "avcodec.h" | #include "avcodec.h" | ||||||
|  | #include "bsf.h" | ||||||
| #include "bytestream.h" | #include "bytestream.h" | ||||||
| #include "hevc.h" | #include "hevc.h" | ||||||
|  |  | ||||||
| @@ -33,11 +34,9 @@ | |||||||
| typedef struct HEVCBSFContext { | typedef struct HEVCBSFContext { | ||||||
|     uint8_t  length_size; |     uint8_t  length_size; | ||||||
|     int      extradata_parsed; |     int      extradata_parsed; | ||||||
|  |  | ||||||
|     int logged_nonmp4_warning; |  | ||||||
| } HEVCBSFContext; | } HEVCBSFContext; | ||||||
|  |  | ||||||
| static int hevc_extradata_to_annexb(AVCodecContext *avctx) | static int hevc_extradata_to_annexb(AVBSFContext *ctx) | ||||||
| { | { | ||||||
|     GetByteContext gb; |     GetByteContext gb; | ||||||
|     int length_size, num_arrays, i, j; |     int length_size, num_arrays, i, j; | ||||||
| @@ -46,7 +45,7 @@ static int hevc_extradata_to_annexb(AVCodecContext *avctx) | |||||||
|     uint8_t *new_extradata = NULL; |     uint8_t *new_extradata = NULL; | ||||||
|     size_t   new_extradata_size = 0;; |     size_t   new_extradata_size = 0;; | ||||||
|  |  | ||||||
|     bytestream2_init(&gb, avctx->extradata, avctx->extradata_size); |     bytestream2_init(&gb, ctx->par_in->extradata, ctx->par_in->extradata_size); | ||||||
|  |  | ||||||
|     bytestream2_skip(&gb, 21); |     bytestream2_skip(&gb, 21); | ||||||
|     length_size = (bytestream2_get_byte(&gb) & 3) + 1; |     length_size = (bytestream2_get_byte(&gb) & 3) + 1; | ||||||
| @@ -58,7 +57,7 @@ static int hevc_extradata_to_annexb(AVCodecContext *avctx) | |||||||
|  |  | ||||||
|         if (!(type == NAL_VPS || type == NAL_SPS || type == NAL_PPS || |         if (!(type == NAL_VPS || type == NAL_SPS || type == NAL_PPS || | ||||||
|               type == NAL_SEI_PREFIX || type == NAL_SEI_SUFFIX)) { |               type == NAL_SEI_PREFIX || type == NAL_SEI_SUFFIX)) { | ||||||
|             av_log(avctx, AV_LOG_ERROR, "Invalid NAL unit type in extradata: %d\n", |             av_log(ctx, AV_LOG_ERROR, "Invalid NAL unit type in extradata: %d\n", | ||||||
|                    type); |                    type); | ||||||
|             ret = AVERROR_INVALIDDATA; |             ret = AVERROR_INVALIDDATA; | ||||||
|             goto fail; |             goto fail; | ||||||
| @@ -82,12 +81,12 @@ static int hevc_extradata_to_annexb(AVCodecContext *avctx) | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     av_freep(&avctx->extradata); |     av_freep(&ctx->par_out->extradata); | ||||||
|     avctx->extradata      = new_extradata; |     ctx->par_out->extradata      = new_extradata; | ||||||
|     avctx->extradata_size = new_extradata_size; |     ctx->par_out->extradata_size = new_extradata_size; | ||||||
|  |  | ||||||
|     if (!new_extradata_size) |     if (!new_extradata_size) | ||||||
|         av_log(avctx, AV_LOG_WARNING, "No parameter sets in the extradata\n"); |         av_log(ctx, AV_LOG_WARNING, "No parameter sets in the extradata\n"); | ||||||
|  |  | ||||||
|     return length_size; |     return length_size; | ||||||
| fail: | fail: | ||||||
| @@ -95,52 +94,54 @@ fail: | |||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int hevc_mp4toannexb_filter(AVBitStreamFilterContext *bsfc, | static int hevc_mp4toannexb_init(AVBSFContext *ctx) | ||||||
|                                    AVCodecContext *avctx, const char *args, |  | ||||||
|                                    uint8_t **poutbuf, int *poutbuf_size, |  | ||||||
|                                    const uint8_t *buf, int buf_size, |  | ||||||
|                                    int keyframe) |  | ||||||
| { | { | ||||||
|     HEVCBSFContext *ctx = bsfc->priv_data; |     HEVCBSFContext *s = ctx->priv_data; | ||||||
|  |     int ret; | ||||||
|  |  | ||||||
|  |     if (ctx->par_in->extradata_size < MIN_HEVCC_LENGTH || | ||||||
|  |         AV_RB24(ctx->par_in->extradata) == 1           || | ||||||
|  |         AV_RB32(ctx->par_in->extradata) == 1) { | ||||||
|  |         av_log(ctx, AV_LOG_VERBOSE, | ||||||
|  |                "The input looks like it is Annex B already\n"); | ||||||
|  |     } else { | ||||||
|  |         ret = hevc_extradata_to_annexb(ctx); | ||||||
|  |         if (ret < 0) | ||||||
|  |             return ret; | ||||||
|  |         s->length_size      = ret; | ||||||
|  |         s->extradata_parsed = 1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int hevc_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out) | ||||||
|  | { | ||||||
|  |     HEVCBSFContext *s = ctx->priv_data; | ||||||
|  |     AVPacket *in; | ||||||
|     GetByteContext gb; |     GetByteContext gb; | ||||||
|  |  | ||||||
|     uint8_t *out = NULL; |  | ||||||
|     size_t   out_size = 0; |  | ||||||
|     int got_irap = 0; |     int got_irap = 0; | ||||||
|     int i, ret = 0; |     int i, ret = 0; | ||||||
|  |  | ||||||
|     if (!ctx->extradata_parsed) { |     ret = ff_bsf_get_packet(ctx, &in); | ||||||
|         if (avctx->extradata_size < MIN_HEVCC_LENGTH || |     if (ret < 0) | ||||||
|             AV_RB24(avctx->extradata) == 1           || |         return ret; | ||||||
|             AV_RB32(avctx->extradata) == 1) { |  | ||||||
|             if (!ctx->logged_nonmp4_warning) { |  | ||||||
|                 av_log(avctx, AV_LOG_VERBOSE, |  | ||||||
|                        "The input looks like it is Annex B already\n"); |  | ||||||
|                 ctx->logged_nonmp4_warning = 1; |  | ||||||
|             } |  | ||||||
|             *poutbuf      = buf; |  | ||||||
|             *poutbuf_size = buf_size; |  | ||||||
|             return 0; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         ret = hevc_extradata_to_annexb(avctx); |     if (!s->extradata_parsed) { | ||||||
|         if (ret < 0) |         av_packet_move_ref(out, in); | ||||||
|             return ret; |         av_packet_free(&in); | ||||||
|         ctx->length_size      = ret; |         return 0; | ||||||
|         ctx->extradata_parsed = 1; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     *poutbuf_size = 0; |     bytestream2_init(&gb, in->data, in->size); | ||||||
|     *poutbuf      = NULL; |  | ||||||
|  |  | ||||||
|     bytestream2_init(&gb, buf, buf_size); |  | ||||||
|  |  | ||||||
|     while (bytestream2_get_bytes_left(&gb)) { |     while (bytestream2_get_bytes_left(&gb)) { | ||||||
|         uint32_t nalu_size = 0; |         uint32_t nalu_size = 0; | ||||||
|         int      nalu_type; |         int      nalu_type; | ||||||
|         int is_irap, add_extradata, extra_size; |         int is_irap, add_extradata, extra_size, prev_size; | ||||||
|  |  | ||||||
|         for (i = 0; i < ctx->length_size; i++) |         for (i = 0; i < s->length_size; i++) | ||||||
|             nalu_size = (nalu_size << 8) | bytestream2_get_byte(&gb); |             nalu_size = (nalu_size << 8) | bytestream2_get_byte(&gb); | ||||||
|  |  | ||||||
|         nalu_type = (bytestream2_peek_byte(&gb) >> 1) & 0x3f; |         nalu_type = (bytestream2_peek_byte(&gb) >> 1) & 0x3f; | ||||||
| @@ -148,39 +149,47 @@ static int hevc_mp4toannexb_filter(AVBitStreamFilterContext *bsfc, | |||||||
|         /* prepend extradata to IRAP frames */ |         /* prepend extradata to IRAP frames */ | ||||||
|         is_irap       = nalu_type >= 16 && nalu_type <= 23; |         is_irap       = nalu_type >= 16 && nalu_type <= 23; | ||||||
|         add_extradata = is_irap && !got_irap; |         add_extradata = is_irap && !got_irap; | ||||||
|         extra_size    = add_extradata * avctx->extradata_size; |         extra_size    = add_extradata * ctx->par_out->extradata_size; | ||||||
|         got_irap     |= is_irap; |         got_irap     |= is_irap; | ||||||
|  |  | ||||||
|         if (SIZE_MAX - out_size < 4             || |         if (SIZE_MAX - nalu_size < 4 || | ||||||
|             SIZE_MAX - out_size - 4 < nalu_size || |             SIZE_MAX - 4 - nalu_size < extra_size) { | ||||||
|             SIZE_MAX - out_size - 4 - nalu_size < extra_size) { |  | ||||||
|             ret = AVERROR_INVALIDDATA; |             ret = AVERROR_INVALIDDATA; | ||||||
|             goto fail; |             goto fail; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         ret = av_reallocp(&out, out_size + 4 + nalu_size + extra_size); |         prev_size = out->size; | ||||||
|  |  | ||||||
|  |         ret = av_grow_packet(out, 4 + nalu_size + extra_size); | ||||||
|         if (ret < 0) |         if (ret < 0) | ||||||
|             goto fail; |             goto fail; | ||||||
|  |  | ||||||
|         if (add_extradata) |         if (add_extradata) | ||||||
|             memcpy(out + out_size, avctx->extradata, extra_size); |             memcpy(out->data + prev_size, ctx->par_out->extradata, extra_size); | ||||||
|         AV_WB32(out + out_size + extra_size, 1); |         AV_WB32(out->data + prev_size + extra_size, 1); | ||||||
|         bytestream2_get_buffer(&gb, out + out_size + 4 + extra_size, nalu_size); |         bytestream2_get_buffer(&gb, out->data + prev_size + 4 + extra_size, nalu_size); | ||||||
|         out_size += 4 + nalu_size + extra_size; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     *poutbuf      = out; |     ret = av_packet_copy_props(out, in); | ||||||
|     *poutbuf_size = out_size; |     if (ret < 0) | ||||||
|  |         goto fail; | ||||||
|     return 1; |  | ||||||
|  |  | ||||||
| fail: | fail: | ||||||
|     av_freep(&out); |     if (ret < 0) | ||||||
|  |         av_packet_unref(out); | ||||||
|  |     av_packet_free(&in); | ||||||
|  |  | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| AVBitStreamFilter ff_hevc_mp4toannexb_bsf = { | static const enum AVCodecID codec_ids[] = { | ||||||
|     "hevc_mp4toannexb", |     AV_CODEC_ID_HEVC, AV_CODEC_ID_NONE, | ||||||
|     sizeof(HEVCBSFContext), | }; | ||||||
|     hevc_mp4toannexb_filter, |  | ||||||
|  | const AVBitStreamFilter ff_hevc_mp4toannexb_bsf = { | ||||||
|  |     .name           = "hevc_mp4toannexb", | ||||||
|  |     .priv_data_size = sizeof(HEVCBSFContext), | ||||||
|  |     .init           = hevc_mp4toannexb_init, | ||||||
|  |     .filter         = hevc_mp4toannexb_filter, | ||||||
|  |     .codec_ids      = codec_ids, | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -26,36 +26,51 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include "avcodec.h" | #include "avcodec.h" | ||||||
|  | #include "bsf.h" | ||||||
| #include "bytestream.h" | #include "bytestream.h" | ||||||
|  |  | ||||||
|  |  | ||||||
| static int imx_dump_header(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, | static int imx_dump_header(AVBSFContext *ctx, AVPacket *out) | ||||||
|                            uint8_t **poutbuf, int *poutbuf_size, |  | ||||||
|                            const uint8_t *buf, int buf_size, int keyframe) |  | ||||||
| { | { | ||||||
|     /* MXF essence element key */ |     /* MXF essence element key */ | ||||||
|     static const uint8_t imx_header[16] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x05,0x01,0x01,0x00 }; |     static const uint8_t imx_header[16] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x05,0x01,0x01,0x00 }; | ||||||
|     uint8_t *poutbufp; |  | ||||||
|  |  | ||||||
|     if (avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO) { |     AVPacket *in; | ||||||
|         av_log(avctx, AV_LOG_ERROR, "imx bitstream filter only applies to mpeg2video codec\n"); |     int ret = 0; | ||||||
|         return 0; |     uint8_t *out_buf; | ||||||
|     } |  | ||||||
|  |  | ||||||
|     *poutbuf = av_malloc(buf_size + 20 + AV_INPUT_BUFFER_PADDING_SIZE); |     ret = ff_bsf_get_packet(ctx, &in); | ||||||
|     if (!*poutbuf) |     if (ret < 0) | ||||||
|         return AVERROR(ENOMEM); |         return ret; | ||||||
|     poutbufp = *poutbuf; |  | ||||||
|     bytestream_put_buffer(&poutbufp, imx_header, 16); |     ret = av_new_packet(out, in->size + 20); | ||||||
|     bytestream_put_byte(&poutbufp, 0x83); /* KLV BER long form */ |     if (ret < 0) | ||||||
|     bytestream_put_be24(&poutbufp, buf_size); |         goto fail; | ||||||
|     bytestream_put_buffer(&poutbufp, buf, buf_size); |  | ||||||
|     *poutbuf_size = poutbufp - *poutbuf; |     out_buf = out->data; | ||||||
|     return 1; |  | ||||||
|  |     bytestream_put_buffer(&out_buf, imx_header, 16); | ||||||
|  |     bytestream_put_byte(&out_buf, 0x83); /* KLV BER long form */ | ||||||
|  |     bytestream_put_be24(&out_buf, in->size); | ||||||
|  |     bytestream_put_buffer(&out_buf, in->data, in->size); | ||||||
|  |  | ||||||
|  |     ret = av_packet_copy_props(out, in); | ||||||
|  |     if (ret < 0) | ||||||
|  |         goto fail; | ||||||
|  |  | ||||||
|  | fail: | ||||||
|  |     if (ret < 0) | ||||||
|  |         av_packet_unref(out); | ||||||
|  |     av_packet_free(&in); | ||||||
|  |     return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| AVBitStreamFilter ff_imx_dump_header_bsf = { | static const enum AVCodecID codec_ids[] = { | ||||||
|     "imxdump", |     AV_CODEC_ID_MPEG2VIDEO, AV_CODEC_ID_NONE, | ||||||
|     0, | }; | ||||||
|     imx_dump_header, |  | ||||||
|  | const AVBitStreamFilter ff_imx_dump_header_bsf = { | ||||||
|  |     .name      = "imxdump", | ||||||
|  |     .filter    = imx_dump_header, | ||||||
|  |     .codec_ids = codec_ids, | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -30,6 +30,7 @@ | |||||||
| #include "libavutil/mem.h" | #include "libavutil/mem.h" | ||||||
|  |  | ||||||
| #include "avcodec.h" | #include "avcodec.h" | ||||||
|  | #include "bsf.h" | ||||||
| #include "jpegtables.h" | #include "jpegtables.h" | ||||||
|  |  | ||||||
| static const uint8_t jpeg_header[] = { | static const uint8_t jpeg_header[] = { | ||||||
| @@ -75,42 +76,56 @@ static uint8_t *append_dht_segment(uint8_t *buf) | |||||||
|     return buf; |     return buf; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int mjpeg2jpeg_filter(AVBitStreamFilterContext *bsfc, | static int mjpeg2jpeg_filter(AVBSFContext *ctx, AVPacket *out) | ||||||
|                              AVCodecContext *avctx, const char *args, |  | ||||||
|                              uint8_t **poutbuf, int *poutbuf_size, |  | ||||||
|                              const uint8_t *buf, int buf_size, |  | ||||||
|                              int keyframe) |  | ||||||
| { | { | ||||||
|  |     AVPacket *in; | ||||||
|  |     int ret = 0; | ||||||
|     int input_skip, output_size; |     int input_skip, output_size; | ||||||
|     uint8_t *output, *out; |     uint8_t *output; | ||||||
|  |  | ||||||
|     if (buf_size < 12) { |     ret = ff_bsf_get_packet(ctx, &in); | ||||||
|         av_log(avctx, AV_LOG_ERROR, "input is truncated\n"); |  | ||||||
|         return AVERROR_INVALIDDATA; |     if (in->size < 12) { | ||||||
|  |         av_log(ctx, AV_LOG_ERROR, "input is truncated\n"); | ||||||
|  |         ret = AVERROR_INVALIDDATA; | ||||||
|  |         goto fail; | ||||||
|     } |     } | ||||||
|     if (memcmp("AVI1", buf + 6, 4)) { |     if (memcmp("AVI1", in->data + 6, 4)) { | ||||||
|         av_log(avctx, AV_LOG_ERROR, "input is not MJPEG/AVI1\n"); |         av_log(ctx, AV_LOG_ERROR, "input is not MJPEG/AVI1\n"); | ||||||
|         return AVERROR_INVALIDDATA; |         ret = AVERROR_INVALIDDATA; | ||||||
|  |         goto fail; | ||||||
|     } |     } | ||||||
|     input_skip = (buf[4] << 8) + buf[5] + 4; |  | ||||||
|     if (buf_size < input_skip) { |     input_skip = (in->data[4] << 8) + in->data[5] + 4; | ||||||
|         av_log(avctx, AV_LOG_ERROR, "input is truncated\n"); |     if (in->size < input_skip) { | ||||||
|         return AVERROR_INVALIDDATA; |         av_log(ctx, AV_LOG_ERROR, "input is truncated\n"); | ||||||
|  |         ret = AVERROR_INVALIDDATA; | ||||||
|  |         goto fail; | ||||||
|     } |     } | ||||||
|     output_size = buf_size - input_skip + |     output_size = in->size - input_skip + | ||||||
|                   sizeof(jpeg_header) + dht_segment_size; |                   sizeof(jpeg_header) + dht_segment_size; | ||||||
|     output = out = av_malloc(output_size); |     ret = av_new_packet(out, output_size); | ||||||
|     if (!output) |     if (ret < 0) | ||||||
|         return AVERROR(ENOMEM); |         goto fail; | ||||||
|     out = append(out, jpeg_header, sizeof(jpeg_header)); |  | ||||||
|     out = append_dht_segment(out); |     output = out->data; | ||||||
|     out = append(out, buf + input_skip, buf_size - input_skip); |  | ||||||
|     *poutbuf = output; |     output = append(output, jpeg_header, sizeof(jpeg_header)); | ||||||
|     *poutbuf_size = output_size; |     output = append_dht_segment(output); | ||||||
|     return 1; |     output = append(output, in->data + input_skip, in->size - input_skip); | ||||||
|  |  | ||||||
|  |     ret = av_packet_copy_props(out, in); | ||||||
|  |     if (ret < 0) | ||||||
|  |         goto fail; | ||||||
|  |  | ||||||
|  | fail: | ||||||
|  |     if (ret < 0) | ||||||
|  |         av_packet_unref(out); | ||||||
|  |     av_packet_free(&in); | ||||||
|  |     return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| AVBitStreamFilter ff_mjpeg2jpeg_bsf = { | const AVBitStreamFilter ff_mjpeg2jpeg_bsf = { | ||||||
|     .name           = "mjpeg2jpeg", |     .name           = "mjpeg2jpeg", | ||||||
|     .filter         = mjpeg2jpeg_filter, |     .filter         = mjpeg2jpeg_filter, | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -26,71 +26,83 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include "avcodec.h" | #include "avcodec.h" | ||||||
|  | #include "bsf.h" | ||||||
| #include "bytestream.h" | #include "bytestream.h" | ||||||
| #include "mjpeg.h" | #include "mjpeg.h" | ||||||
|  |  | ||||||
|  |  | ||||||
| static int mjpega_dump_header(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, | static int mjpega_dump_header(AVBSFContext *ctx, AVPacket *out) | ||||||
|                               uint8_t **poutbuf, int *poutbuf_size, |  | ||||||
|                               const uint8_t *buf, int buf_size, int keyframe) |  | ||||||
| { | { | ||||||
|     uint8_t *poutbufp; |     AVPacket *in; | ||||||
|  |     uint8_t *out_buf; | ||||||
|     unsigned dqt = 0, dht = 0, sof0 = 0; |     unsigned dqt = 0, dht = 0, sof0 = 0; | ||||||
|     int i; |     int ret = 0, i; | ||||||
|  |  | ||||||
|     if (avctx->codec_id != AV_CODEC_ID_MJPEG) { |     ret = ff_bsf_get_packet(ctx, &in); | ||||||
|         av_log(avctx, AV_LOG_ERROR, "mjpega bitstream filter only applies to mjpeg codec\n"); |     if (ret < 0) | ||||||
|         return 0; |         return ret; | ||||||
|     } |  | ||||||
|  |  | ||||||
|     *poutbuf_size = 0; |     ret = av_new_packet(out, in->size + 44); | ||||||
|     *poutbuf = av_malloc(buf_size + 44 + AV_INPUT_BUFFER_PADDING_SIZE); |     if (ret < 0) | ||||||
|     if (!*poutbuf) |         goto fail; | ||||||
|         return AVERROR(ENOMEM); |  | ||||||
|     poutbufp = *poutbuf; |  | ||||||
|     bytestream_put_byte(&poutbufp, 0xff); |  | ||||||
|     bytestream_put_byte(&poutbufp, SOI); |  | ||||||
|     bytestream_put_byte(&poutbufp, 0xff); |  | ||||||
|     bytestream_put_byte(&poutbufp, APP1); |  | ||||||
|     bytestream_put_be16(&poutbufp, 42); /* size */ |  | ||||||
|     bytestream_put_be32(&poutbufp, 0); |  | ||||||
|     bytestream_put_buffer(&poutbufp, "mjpg", 4); |  | ||||||
|     bytestream_put_be32(&poutbufp, buf_size + 44); /* field size */ |  | ||||||
|     bytestream_put_be32(&poutbufp, buf_size + 44); /* pad field size */ |  | ||||||
|     bytestream_put_be32(&poutbufp, 0);             /* next ptr */ |  | ||||||
|  |  | ||||||
|     for (i = 0; i < buf_size - 1; i++) { |     ret = av_packet_copy_props(out, in); | ||||||
|         if (buf[i] == 0xff) { |     if (ret < 0) | ||||||
|             switch (buf[i + 1]) { |         goto fail; | ||||||
|  |  | ||||||
|  |     out_buf = out->data; | ||||||
|  |     bytestream_put_byte(&out_buf, 0xff); | ||||||
|  |     bytestream_put_byte(&out_buf, SOI); | ||||||
|  |     bytestream_put_byte(&out_buf, 0xff); | ||||||
|  |     bytestream_put_byte(&out_buf, APP1); | ||||||
|  |     bytestream_put_be16(&out_buf, 42); /* size */ | ||||||
|  |     bytestream_put_be32(&out_buf, 0); | ||||||
|  |     bytestream_put_buffer(&out_buf, "mjpg", 4); | ||||||
|  |     bytestream_put_be32(&out_buf, in->size + 44); /* field size */ | ||||||
|  |     bytestream_put_be32(&out_buf, in->size + 44); /* pad field size */ | ||||||
|  |     bytestream_put_be32(&out_buf, 0);             /* next ptr */ | ||||||
|  |  | ||||||
|  |     for (i = 0; i < in->size - 1; i++) { | ||||||
|  |         if (in->data[i] == 0xff) { | ||||||
|  |             switch (in->data[i + 1]) { | ||||||
|             case DQT:  dqt  = i + 46; break; |             case DQT:  dqt  = i + 46; break; | ||||||
|             case DHT:  dht  = i + 46; break; |             case DHT:  dht  = i + 46; break; | ||||||
|             case SOF0: sof0 = i + 46; break; |             case SOF0: sof0 = i + 46; break; | ||||||
|             case SOS: |             case SOS: | ||||||
|                 bytestream_put_be32(&poutbufp, dqt); /* quant off */ |                 bytestream_put_be32(&out_buf, dqt); /* quant off */ | ||||||
|                 bytestream_put_be32(&poutbufp, dht); /* huff off */ |                 bytestream_put_be32(&out_buf, dht); /* huff off */ | ||||||
|                 bytestream_put_be32(&poutbufp, sof0); /* image off */ |                 bytestream_put_be32(&out_buf, sof0); /* image off */ | ||||||
|                 bytestream_put_be32(&poutbufp, i + 46); /* scan off */ |                 bytestream_put_be32(&out_buf, i + 46); /* scan off */ | ||||||
|                 bytestream_put_be32(&poutbufp, i + 46 + AV_RB16(buf + i + 2)); /* data off */ |                 bytestream_put_be32(&out_buf, i + 46 + AV_RB16(in->data + i + 2)); /* data off */ | ||||||
|                 bytestream_put_buffer(&poutbufp, buf + 2, buf_size - 2); /* skip already written SOI */ |                 bytestream_put_buffer(&out_buf, in->data + 2, in->size - 2); /* skip already written SOI */ | ||||||
|                 *poutbuf_size = poutbufp - *poutbuf; |  | ||||||
|                 return 1; |                 out->size = out_buf - out->data; | ||||||
|  |                 av_packet_free(&in); | ||||||
|  |                 return 0; | ||||||
|             case APP1: |             case APP1: | ||||||
|                 if (i + 8 < buf_size && AV_RL32(buf + i + 8) == AV_RL32("mjpg")) { |                 if (i + 8 < in->size && AV_RL32(in->data + i + 8) == AV_RL32("mjpg")) { | ||||||
|                     av_log(avctx, AV_LOG_ERROR, "bitstream already formatted\n"); |                     av_log(ctx, AV_LOG_ERROR, "bitstream already formatted\n"); | ||||||
|                     memcpy(*poutbuf, buf, buf_size); |                     av_packet_unref(out); | ||||||
|                     *poutbuf_size = buf_size; |                     av_packet_move_ref(out, in); | ||||||
|                     return 1; |                     av_packet_free(&in); | ||||||
|  |                     return 0; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     av_freep(poutbuf); |     av_log(ctx, AV_LOG_ERROR, "could not find SOS marker in bitstream\n"); | ||||||
|     av_log(avctx, AV_LOG_ERROR, "could not find SOS marker in bitstream\n"); | fail: | ||||||
|     return 0; |     av_packet_unref(out); | ||||||
|  |     av_packet_free(&in); | ||||||
|  |     return AVERROR_INVALIDDATA; | ||||||
| } | } | ||||||
|  |  | ||||||
| AVBitStreamFilter ff_mjpega_dump_header_bsf = { | static const enum AVCodecID codec_ids[] = { | ||||||
|     "mjpegadump", |     AV_CODEC_ID_MJPEG, AV_CODEC_ID_NONE, | ||||||
|     0, | }; | ||||||
|     mjpega_dump_header, |  | ||||||
|  | const AVBitStreamFilter ff_mjpega_dump_header_bsf = { | ||||||
|  |     .name      = "mjpegadump", | ||||||
|  |     .filter    = mjpega_dump_header, | ||||||
|  |     .codec_ids = codec_ids, | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -21,41 +21,79 @@ | |||||||
| #include "libavutil/common.h" | #include "libavutil/common.h" | ||||||
| #include "libavutil/intreadwrite.h" | #include "libavutil/intreadwrite.h" | ||||||
| #include "avcodec.h" | #include "avcodec.h" | ||||||
|  | #include "bsf.h" | ||||||
|  |  | ||||||
|  | static int text2movsub(AVBSFContext *ctx, AVPacket *out) | ||||||
|  | { | ||||||
|  |     AVPacket *in; | ||||||
|  |     int ret = 0; | ||||||
|  |  | ||||||
| static int text2movsub(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, |     ret = ff_bsf_get_packet(ctx, &in); | ||||||
|                      uint8_t **poutbuf, int *poutbuf_size, |     if (ret < 0) | ||||||
|                      const uint8_t *buf, int buf_size, int keyframe){ |         return ret; | ||||||
|     if (buf_size > 0xffff) return 0; |  | ||||||
|     *poutbuf_size = buf_size + 2; |     if (in->size > 0xffff) { | ||||||
|     *poutbuf = av_malloc(*poutbuf_size + AV_INPUT_BUFFER_PADDING_SIZE); |         ret = AVERROR_INVALIDDATA; | ||||||
|     if (!*poutbuf) |         goto fail; | ||||||
|         return AVERROR(ENOMEM); |     } | ||||||
|     AV_WB16(*poutbuf, buf_size); |  | ||||||
|     memcpy(*poutbuf + 2, buf, buf_size); |     ret = av_new_packet(out, in->size + 2); | ||||||
|     return 1; |     if (ret < 0) { | ||||||
|  |         ret = AVERROR(ENOMEM); | ||||||
|  |         goto fail; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ret = av_packet_copy_props(out, in); | ||||||
|  |     if (ret < 0) | ||||||
|  |         goto fail; | ||||||
|  |  | ||||||
|  |     AV_WB16(out->data, in->size); | ||||||
|  |     memcpy(out->data + 2, in->data, in->size); | ||||||
|  |  | ||||||
|  | fail: | ||||||
|  |     if (ret < 0) | ||||||
|  |         av_packet_unref(out); | ||||||
|  |     av_packet_free(&in); | ||||||
|  |     return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| AVBitStreamFilter ff_text2movsub_bsf={ | const AVBitStreamFilter ff_text2movsub_bsf = { | ||||||
|     "text2movsub", |     .name   = "text2movsub", | ||||||
|     0, |     .filter = text2movsub, | ||||||
|     text2movsub, |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static int mov2textsub(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, | static int mov2textsub(AVBSFContext *ctx, AVPacket *out) | ||||||
|                      uint8_t **poutbuf, int *poutbuf_size, | { | ||||||
|                      const uint8_t *buf, int buf_size, int keyframe){ |     AVPacket *in; | ||||||
|     if (buf_size < 2) return 0; |     int ret = 0; | ||||||
|     *poutbuf_size = FFMIN(buf_size - 2, AV_RB16(buf)); |  | ||||||
|     *poutbuf = av_malloc(*poutbuf_size + AV_INPUT_BUFFER_PADDING_SIZE); |     ret = ff_bsf_get_packet(ctx, &in); | ||||||
|     if (!*poutbuf) |     if (ret < 0) | ||||||
|         return AVERROR(ENOMEM); |         return ret; | ||||||
|     memcpy(*poutbuf, buf + 2, *poutbuf_size); |  | ||||||
|     return 1; |     if (in->size < 2) { | ||||||
|  |        ret = AVERROR_INVALIDDATA; | ||||||
|  |        goto fail; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ret = av_new_packet(out, FFMIN(in->size - 2, AV_RB16(in->data))); | ||||||
|  |     if (ret < 0) | ||||||
|  |         goto fail; | ||||||
|  |  | ||||||
|  |     ret = av_packet_copy_props(out, in); | ||||||
|  |     if (ret < 0) | ||||||
|  |         goto fail; | ||||||
|  |  | ||||||
|  |     memcpy(out->data, in->data + 2, out->size); | ||||||
|  |  | ||||||
|  | fail: | ||||||
|  |     if (ret < 0) | ||||||
|  |         av_packet_unref(out); | ||||||
|  |     av_packet_free(&in); | ||||||
|  |     return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| AVBitStreamFilter ff_mov2textsub_bsf={ | const AVBitStreamFilter ff_mov2textsub_bsf = { | ||||||
|     "mov2textsub", |     .name   = "mov2textsub", | ||||||
|     0, |     .filter = mov2textsub, | ||||||
|     mov2textsub, |  | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -22,30 +22,67 @@ | |||||||
| #include <string.h> | #include <string.h> | ||||||
|  |  | ||||||
| #include "avcodec.h" | #include "avcodec.h" | ||||||
|  | #include "bsf.h" | ||||||
|  |  | ||||||
|  | #include "libavutil/log.h" | ||||||
| #include "libavutil/mem.h" | #include "libavutil/mem.h" | ||||||
|  | #include "libavutil/opt.h" | ||||||
|  |  | ||||||
|  | typedef struct NoiseContext { | ||||||
|  |     const AVClass *class; | ||||||
|  |     int amount; | ||||||
|  |     unsigned int state; | ||||||
|  | } NoiseContext; | ||||||
|  |  | ||||||
| static int noise(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, | static int noise(AVBSFContext *ctx, AVPacket *out) | ||||||
|                      uint8_t **poutbuf, int *poutbuf_size, | { | ||||||
|                      const uint8_t *buf, int buf_size, int keyframe){ |     NoiseContext *s = ctx->priv_data; | ||||||
|     unsigned int *state= bsfc->priv_data; |     AVPacket *in; | ||||||
|     int amount= args ? atoi(args) : (*state % 10001+1); |     int amount = s->amount > 0 ? s->amount : (s->state % 10001 + 1); | ||||||
|     int i; |     int i, ret = 0; | ||||||
|  |  | ||||||
|     *poutbuf= av_malloc(buf_size + AV_INPUT_BUFFER_PADDING_SIZE); |     ret = ff_bsf_get_packet(ctx, &in); | ||||||
|     if (!*poutbuf) |     if (ret < 0) | ||||||
|         return AVERROR(ENOMEM); |         return ret; | ||||||
|     memcpy(*poutbuf, buf, buf_size + AV_INPUT_BUFFER_PADDING_SIZE); |  | ||||||
|     for(i=0; i<buf_size; i++){ |     ret = av_new_packet(out, in->size); | ||||||
|         (*state) += (*poutbuf)[i] + 1; |     if (ret < 0) | ||||||
|         if(*state % amount == 0) |         goto fail; | ||||||
|             (*poutbuf)[i] = *state; |  | ||||||
|  |     ret = av_packet_copy_props(out, in); | ||||||
|  |     if (ret < 0) | ||||||
|  |         goto fail; | ||||||
|  |  | ||||||
|  |     memcpy(out->data, in->data, in->size); | ||||||
|  |  | ||||||
|  |     for (i = 0; i < out->size; i++) { | ||||||
|  |         s->state += out->data[i] + 1; | ||||||
|  |         if (s->state % amount == 0) | ||||||
|  |             out->data[i] = s->state; | ||||||
|     } |     } | ||||||
|     return 1; | fail: | ||||||
|  |     if (ret < 0) | ||||||
|  |         av_packet_unref(out); | ||||||
|  |     av_packet_free(&in); | ||||||
|  |     return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| AVBitStreamFilter ff_noise_bsf={ | #define OFFSET(x) offsetof(NoiseContext, x) | ||||||
|     "noise", | static const AVOption options[] = { | ||||||
|     sizeof(int), |     { "amount", NULL, OFFSET(amount), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX }, | ||||||
|     noise, |     { NULL }, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static const AVClass noise_class = { | ||||||
|  |     .class_name = "noise", | ||||||
|  |     .item_name  = av_default_item_name, | ||||||
|  |     .option     = options, | ||||||
|  |     .version    = LIBAVUTIL_VERSION_INT, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const AVBitStreamFilter ff_noise_bsf = { | ||||||
|  |     .name           = "noise", | ||||||
|  |     .priv_data_size = sizeof(int), | ||||||
|  |     .priv_class     = &noise_class, | ||||||
|  |     .filter         = noise, | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -18,39 +18,99 @@ | |||||||
|  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | #include "libavutil/log.h" | ||||||
|  | #include "libavutil/opt.h" | ||||||
|  |  | ||||||
| #include "avcodec.h" | #include "avcodec.h" | ||||||
|  | #include "bsf.h" | ||||||
|  |  | ||||||
|  | enum RemoveFreq { | ||||||
|  |     REMOVE_FREQ_KEYFRAME, | ||||||
|  |     REMOVE_FREQ_ALL, | ||||||
|  | }; | ||||||
|  |  | ||||||
| static int remove_extradata(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, | typedef struct RemoveExtradataContext { | ||||||
|                      uint8_t **poutbuf, int *poutbuf_size, |     const AVClass *class; | ||||||
|                      const uint8_t *buf, int buf_size, int keyframe){ |     int freq; | ||||||
|     int cmd= args ? *args : 0; |  | ||||||
|     AVCodecParserContext *s; |  | ||||||
|  |  | ||||||
|     if(!bsfc->parser){ |     AVCodecParserContext *parser; | ||||||
|         bsfc->parser= av_parser_init(avctx->codec_id); |     AVCodecContext *avctx; | ||||||
|     } | } RemoveExtradataContext; | ||||||
|     s= bsfc->parser; |  | ||||||
|  |  | ||||||
|     if(s && s->parser->split){ | static int remove_extradata(AVBSFContext *ctx, AVPacket *out) | ||||||
|         if(  (((avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) || | { | ||||||
|                (avctx->flags2 & AV_CODEC_FLAG2_LOCAL_HEADER)) && cmd == 'a') |     RemoveExtradataContext *s = ctx->priv_data; | ||||||
|            ||(!keyframe && cmd=='k') |  | ||||||
|            ||(cmd=='e' || !cmd) |     AVPacket *in; | ||||||
|           ){ |     int ret; | ||||||
|             int i= s->parser->split(avctx, buf, buf_size); |  | ||||||
|             buf += i; |     ret = ff_bsf_get_packet(ctx, &in); | ||||||
|             buf_size -= i; |     if (ret < 0) | ||||||
|  |         return ret; | ||||||
|  |  | ||||||
|  |     if (s->parser && s->parser->parser->split) { | ||||||
|  |         if (s->freq == REMOVE_FREQ_ALL || | ||||||
|  |             (s->freq == REMOVE_FREQ_KEYFRAME && in->flags & AV_PKT_FLAG_KEY)) { | ||||||
|  |             int i = s->parser->parser->split(s->avctx, in->data, in->size); | ||||||
|  |             in->data += i; | ||||||
|  |             in->size -= i; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     *poutbuf= (uint8_t *) buf; |  | ||||||
|     *poutbuf_size= buf_size; |     av_packet_move_ref(out, in); | ||||||
|  |     av_packet_free(&in); | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| AVBitStreamFilter ff_remove_extradata_bsf={ | static int remove_extradata_init(AVBSFContext *ctx) | ||||||
|     "remove_extra", | { | ||||||
|     0, |     RemoveExtradataContext *s = ctx->priv_data; | ||||||
|     remove_extradata, |     int ret; | ||||||
|  |  | ||||||
|  |     s->parser = av_parser_init(ctx->par_in->codec_id); | ||||||
|  |  | ||||||
|  |     if (s->parser) { | ||||||
|  |         s->avctx = avcodec_alloc_context3(NULL); | ||||||
|  |         if (!s->avctx) | ||||||
|  |             return AVERROR(ENOMEM); | ||||||
|  |  | ||||||
|  |         ret = avcodec_parameters_to_context(s->avctx, ctx->par_in); | ||||||
|  |         if (ret < 0) | ||||||
|  |             return ret; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void remove_extradata_close(AVBSFContext *ctx) | ||||||
|  | { | ||||||
|  |     RemoveExtradataContext *s = ctx->priv_data; | ||||||
|  |  | ||||||
|  |     avcodec_free_context(&s->avctx); | ||||||
|  |     av_parser_close(s->parser); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #define OFFSET(x) offsetof(RemoveExtradataContext, x) | ||||||
|  | static const AVOption options[] = { | ||||||
|  |     { "freq", NULL, OFFSET(freq), AV_OPT_TYPE_INT, { .i64 = REMOVE_FREQ_KEYFRAME }, REMOVE_FREQ_KEYFRAME, REMOVE_FREQ_ALL, 0, "freq" }, | ||||||
|  |         { "keyframe", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_KEYFRAME }, .unit = "freq" }, | ||||||
|  |         { "all",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_ALL      }, .unit = "freq" }, | ||||||
|  |     { NULL }, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static const AVClass remove_extradata_class = { | ||||||
|  |     .class_name = "remove_extradata", | ||||||
|  |     .item_name  = av_default_item_name, | ||||||
|  |     .option     = options, | ||||||
|  |     .version    = LIBAVUTIL_VERSION_INT, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const AVBitStreamFilter ff_remove_extradata_bsf = { | ||||||
|  |     .name           = "remove_extra", | ||||||
|  |     .priv_data_size = sizeof(RemoveExtradataContext), | ||||||
|  |     .priv_class     = &remove_extradata_class, | ||||||
|  |     .init           = remove_extradata_init, | ||||||
|  |     .close          = remove_extradata_close, | ||||||
|  |     .filter         = remove_extradata, | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -28,7 +28,7 @@ | |||||||
| #include "libavutil/version.h" | #include "libavutil/version.h" | ||||||
|  |  | ||||||
| #define LIBAVCODEC_VERSION_MAJOR 57 | #define LIBAVCODEC_VERSION_MAJOR 57 | ||||||
| #define LIBAVCODEC_VERSION_MINOR 14 | #define LIBAVCODEC_VERSION_MINOR 15 | ||||||
| #define LIBAVCODEC_VERSION_MICRO  0 | #define LIBAVCODEC_VERSION_MICRO  0 | ||||||
|  |  | ||||||
| #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ | #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ | ||||||
| @@ -197,5 +197,8 @@ | |||||||
| #ifndef FF_API_PRIVATE_OPT | #ifndef FF_API_PRIVATE_OPT | ||||||
| #define FF_API_PRIVATE_OPT      (LIBAVCODEC_VERSION_MAJOR < 59) | #define FF_API_PRIVATE_OPT      (LIBAVCODEC_VERSION_MAJOR < 59) | ||||||
| #endif | #endif | ||||||
|  | #ifndef FF_API_OLD_BSF | ||||||
|  | #define FF_API_OLD_BSF          (LIBAVCODEC_VERSION_MAJOR < 59) | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #endif /* AVCODEC_VERSION_H */ | #endif /* AVCODEC_VERSION_H */ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Anton Khirnov
					Anton Khirnov