📄 ffmpeg.cpp
字号:
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is MPEG4IP. * * The Initial Developer of the Original Code is Cisco Systems Inc. * Portions created by Cisco Systems Inc. are * Copyright (C) Cisco Systems Inc. 2004. All Rights Reserved. * * Contributor(s): * Bill May wmay@cisco.com *//* * mpeg2 video codec with libmpeg2 library */#define DECLARE_CONFIG_VARIABLES#define attribute_deprecated#include "ffmpeg.h"#include "mp4av.h"#include "mp4av_h264.h"#include <mpeg2t/mpeg2t_defines.h>#include "mp4util/mpeg4_sdp.h"#include "mp4util/h264_sdp.h"#include <mpeg2ps/mpeg2_ps.h>#include "ffmpeg_if.h"static SConfigVariable MyConfigVariables[] = { CONFIG_BOOL(CONFIG_USE_FFMPEG, "UseFFmpeg", false),};#define ffmpeg_message (ffmpeg->m_vft->log_msg)//#define DEBUG_FFMPEG_FRAME 1//#define DEBUG_FFMPEG_PTS 1static enum CodecID ffmpeg_find_codec (const char *stream_type, const char *compressor, int type, int profile, format_list_t *fptr, const uint8_t *userdata, uint32_t ud_size){ bool have_mp4_file = strcasecmp(stream_type, STREAM_TYPE_MP4_FILE) == 0; if (have_mp4_file) { if (strcasecmp(compressor, "avc1") == 0) { return CODEC_ID_H264; } if (strcasecmp(compressor, "264b") == 0) { return CODEC_ID_H264; } if (strcasecmp(compressor, "mp4v") == 0) { if (MP4_IS_MPEG1_VIDEO_TYPE(type) || MP4_IS_MPEG2_VIDEO_TYPE(type)) return CODEC_ID_MPEG2VIDEO; if (MP4_IS_MPEG4_VIDEO_TYPE(type)) return CODEC_ID_MPEG4; } } if (have_mp4_file || strcasecmp(stream_type, "QT FILE") == 0) { if (strcasecmp(compressor, "h263") == 0 || strcasecmp(compressor, "s263") == 0) { return CODEC_ID_H263; } if (strcasecmp(compressor, "SVQ3") == 0) { return CODEC_ID_SVQ3; } if (strcasecmp(compressor, "jpeg") == 0) { return CODEC_ID_MJPEG; } return CODEC_ID_NONE; } if (strcasecmp(stream_type, STREAM_TYPE_MPEG_FILE) == 0) { if (type == MPEG_VIDEO_H264) return CODEC_ID_H264; return CODEC_ID_MPEG2VIDEO; } if (strcasecmp(stream_type, STREAM_TYPE_MPEG2_TRANSPORT_STREAM) == 0) { if ((type == MPEG2T_ST_MPEG_VIDEO) || (type == MPEG2T_ST_11172_VIDEO)) return CODEC_ID_MPEG2VIDEO; if (type == MPEG2T_ST_H264_VIDEO) { return CODEC_ID_H264; } if (type == MPEG2T_ST_MPEG4_VIDEO) { return CODEC_ID_MPEG4; } return CODEC_ID_NONE; } if (strcasecmp(stream_type, STREAM_TYPE_AVI_FILE) == 0) { if (strcasecmp(compressor, "vssh") == 0) { return CODEC_ID_H264; } if (strcasecmp(compressor, "H263") == 0) { return CODEC_ID_H263; } if (strcasecmp(compressor, "mjpg") == 0) { return CODEC_ID_MJPEG; } return CODEC_ID_NONE; } if (strcasecmp(stream_type, "QT FILE") == 0) { if (strcasecmp(compressor, "h263") == 0 || strcasecmp(compressor, "s263") == 0) { return CODEC_ID_H263; } return CODEC_ID_NONE; } if ((strcasecmp(stream_type, STREAM_TYPE_RTP) == 0) && fptr != NULL) { if (strcmp(fptr->fmt, "32") == 0) return CODEC_ID_MPEG2VIDEO; if (fptr->rtpmap_name != NULL) { if (strcasecmp(fptr->rtpmap_name, "h263-1998") == 0 || strcasecmp(fptr->rtpmap_name, "h263-2000") == 0) { return CODEC_ID_H263; } if (strcasecmp(fptr->rtpmap_name, "MP4V-ES") == 0) { // may want to check level and profile return CODEC_ID_MPEG4; } if (strcasecmp(fptr->rtpmap_name, "h264") == 0) { // may want to check for sprop-parameters return CODEC_ID_H264; } } return CODEC_ID_NONE; } return CODEC_ID_NONE;}static bool ffmpeg_find_h264_size (ffmpeg_codec_t *ffmpeg, const uint8_t *ud, uint32_t ud_size){ uint32_t offset = 0; ffmpeg_message(LOG_DEBUG, "ffmpeg", "start finding size"); do { if (h264_is_start_code(ud + offset)) { uint8_t nal_type = h264_nal_unit_type(ud + offset); ffmpeg_message(LOG_DEBUG, "ffmpeg", "nal %u", nal_type); if (nal_type == H264_NAL_TYPE_SEQ_PARAM) { h264_decode_t dec; memset(&dec, 0, sizeof(dec)); if (h264_read_seq_info(ud + offset, ud_size - offset, &dec) == 0) { ffmpeg->m_c->width = dec.pic_width; ffmpeg->m_c->height = dec.pic_height; return true; } } } uint32_t result; result = h264_find_next_start_code(ud + offset, ud_size - offset); if (result == 0) offset = ud_size; else offset += result; } while (offset < ud_size); return false;}static codec_data_t *ffmpeg_create (const char *stream_type, const char *compressor, int type, int profile, format_list_t *media_fmt, video_info_t *vinfo, const uint8_t *userdata, uint32_t ud_size, video_vft_t *vft, void *ifptr){ ffmpeg_codec_t *ffmpeg; ffmpeg = MALLOC_STRUCTURE(ffmpeg_codec_t); memset(ffmpeg, 0, sizeof(*ffmpeg)); ffmpeg->m_vft = vft; ffmpeg->m_ifptr = ifptr; avcodec_init(); avcodec_register_all(); av_log_set_level(AV_LOG_QUIET); ffmpeg->m_codecId = ffmpeg_find_codec(stream_type, compressor, type, profile, media_fmt, userdata, ud_size); // must have a codecID - we checked it earlier ffmpeg->m_codec = avcodec_find_decoder(ffmpeg->m_codecId); ffmpeg->m_c = avcodec_alloc_context(); ffmpeg->m_picture = avcodec_alloc_frame(); bool open_codec = true; bool run_userdata = false; bool free_userdata = false; switch (ffmpeg->m_codecId) { case CODEC_ID_MJPEG: break; case CODEC_ID_H264: // need to find height and width if (media_fmt != NULL && media_fmt->fmt_param != NULL) { userdata = h264_sdp_parse_sprop_param_sets(media_fmt->fmt_param, &ud_size, ffmpeg->m_vft->log_msg); if (userdata != NULL) free_userdata = true; ffmpeg_message(LOG_DEBUG, "ffmpeg", "sprop len %d", ud_size); } if (ud_size > 0) { ffmpeg_message(LOG_DEBUG, "ffmpeg", "userdata len %d", ud_size); open_codec = ffmpeg_find_h264_size(ffmpeg, userdata, ud_size); ffmpeg_message(LOG_DEBUG, "ffmpeg", "open codec is %d", open_codec); run_userdata = true; } else { open_codec = false; } break; case CODEC_ID_MPEG4: { fmtp_parse_t *fmtp = NULL; open_codec = false; if (media_fmt != NULL) { fmtp = parse_fmtp_for_mpeg4(media_fmt->fmt_param, ffmpeg->m_vft->log_msg); if (fmtp->config_binary != NULL) { userdata = fmtp->config_binary; ud_size = fmtp->config_binary_len; fmtp->config_binary = NULL; free_userdata = true; } } if (ud_size > 0) { uint8_t *vol = MP4AV_Mpeg4FindVol((uint8_t *)userdata, ud_size); u_int8_t TimeBits; u_int16_t TimeTicks; u_int16_t FrameDuration; u_int16_t FrameWidth; u_int16_t FrameHeight; u_int8_t aspectRatioDefine; u_int8_t aspectRatioWidth; u_int8_t aspectRatioHeight; if (vol) { if (MP4AV_Mpeg4ParseVol(vol, ud_size - (vol - userdata), &TimeBits, &TimeTicks, &FrameDuration, &FrameWidth, &FrameHeight, &aspectRatioDefine, &aspectRatioWidth, &aspectRatioHeight)) { ffmpeg->m_c->width = FrameWidth; ffmpeg->m_c->height = FrameHeight; open_codec = true; run_userdata = true; } } } if (fmtp != NULL) { free_fmtp_parse(fmtp); } } break; case CODEC_ID_SVQ3: ffmpeg->m_c->extradata = (typeof(ffmpeg->m_c->extradata))userdata; ffmpeg->m_c->extradata_size = ud_size; if (vinfo != NULL) { ffmpeg->m_c->width = vinfo->width; ffmpeg->m_c->height = vinfo->height; } break; default: break; } if (open_codec) { ffmpeg_interface_lock(); if (avcodec_open(ffmpeg->m_c, ffmpeg->m_codec) < 0) { ffmpeg_interface_unlock(); ffmpeg_message(LOG_CRIT, "ffmpeg", "failed to open codec"); return NULL; } ffmpeg_interface_unlock(); ffmpeg_message(LOG_DEBUG, "ffmpeg", "pixel format is %d", ffmpeg->m_c->pix_fmt); ffmpeg->m_codec_opened = true; if (run_userdata) { uint32_t offset = 0; do { int got_picture; offset += avcodec_decode_video(ffmpeg->m_c, ffmpeg->m_picture, &got_picture, (uint8_t *)userdata + offset, ud_size - offset); } while (offset < ud_size); } } if (free_userdata) { CHECK_AND_FREE(userdata); } ffmpeg->m_did_pause = 1; return ((codec_data_t *)ffmpeg);}static void ffmpeg_close (codec_data_t *ifptr){ ffmpeg_codec_t *ffmpeg; ffmpeg = (ffmpeg_codec_t *)ifptr; if (ffmpeg->m_c != NULL) { ffmpeg_interface_lock(); avcodec_close(ffmpeg->m_c); ffmpeg_interface_unlock(); free(ffmpeg->m_c); } CHECK_AND_FREE(ffmpeg->m_picture); free(ffmpeg);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -