📄 isma_enc_video_plugin.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. 2001-2004 All Rights Reserved. * * Contributor(s): * Bill May wmay@cisco.com * Alex Vanzella alexv@cisco.com */#include "isma_enc_video_plugin.h"#include "rtp/rtp.h"//#define DEBUG_ISMA_AAC#define isma_message iptr->m_vft->log_msgstatic rtp_check_return_t check (lib_message_func_t msg, format_list_t *fmt, uint8_t rtp_payload_type, CConfigSet *pConfig){ if (fmt == NULL || fmt->rtpmap_name == NULL) return RTP_PLUGIN_NO_MATCH; if ( (strcasecmp(fmt->rtpmap_name, "enc-mpeg4-generic") != 0) ) { return RTP_PLUGIN_NO_MATCH; } if ( (strcasecmp(fmt->media->media, "video") != 0 ) ) { return RTP_PLUGIN_NO_MATCH; } fmtp_parse_t *fmtp; fmtp = parse_fmtp_for_mpeg4(fmt->fmt_param, msg); if (fmtp == NULL) { return RTP_PLUGIN_NO_MATCH; } return RTP_PLUGIN_MATCH;}rtp_plugin_data_t *isma_enc_video_rtp_plugin_create (format_list_t *media_fmt, uint8_t rtp_payload_type, rtp_vft_t *vft, void *ifptr){ isma_enc_video_rtp_data_t *iptr; iptr = MALLOC_STRUCTURE(isma_enc_video_rtp_data_t); if ( iptr == NULL ) return NULL; memset(iptr, 0, sizeof(*iptr)); iptr->m_vft = vft; iptr->m_ifptr = ifptr;#ifdef R2429_RTP_DUMP_OUTPUT_TO_FILE iptr->m_outfile = fopen("rtp.h263", "w");#endif iptr->m_buffer = NULL; iptr->m_buffer_len = 0; iptr->m_buffer_len_max = 0; if (strcasecmp(media_fmt->media->media, "video") == 0) { ismacrypInitSession(&(iptr->myEncSID), KeyTypeVideo); } iptr->frameCount = 0; iptr->mp4SDP = parse_fmtp_for_mpeg4(media_fmt->fmt_param, iptr->m_vft->log_msg); return (&iptr->plug);}static void r2429_rtp_destroy (rtp_plugin_data_t *pifptr){ isma_enc_video_rtp_data_t *iptr = (isma_enc_video_rtp_data_t *)pifptr;#ifdef ISMA_RTP_DUMP_OUTPUT_TO_FILE fclose(iptr->m_outfile);#endif CHECK_AND_FREE(iptr->m_buffer); free(iptr);}static bool start_next_frame (rtp_plugin_data_t *pifptr, uint8_t **buffer, uint32_t *buflen, frame_timestamp_t *ts, void **userdata){ isma_enc_video_rtp_data_t *iptr = (isma_enc_video_rtp_data_t *)pifptr; uint64_t timetick; rtp_packet *rpak; uint32_t rtp_ts; uint64_t ntp_ts; uint8_t *dptr; uint32_t dlen; uint32_t IV; uint16_t seq; rpak = (iptr->m_vft->get_next_pak)(iptr->m_ifptr, NULL, 1); seq = rpak->rtp_pak_seq; iptr->frameCount++; // awv notes: 1. video frames can be fragmented across several rtp packets. // 2. each fragment has the appropriate ismacryp streaming header // (i.e. IV in our case since that is all that is supported). // 3. important: the complete frame once all ismacryp streaming // headers are removed still has the header from when it was // encrypted. (i.e. IV again in our case) while (rpak != NULL) { iptr->m_buffer_len = 0; rtp_ts = rpak->rtp_pak_ts; ntp_ts = rpak->pd.rtp_pd_timestamp; do { dptr = rpak->rtp_data; dlen = rpak->rtp_data_len; if ( rpak->rtp_pak_seq - seq > 1 ) { return false; } else seq = rpak->rtp_pak_seq; // awv notes. 1. the first frame has stream config info prepended to the // video frame. we need to remove this. // 2. each fragment of video frame has the mysterious 00 20 // header which looks like rfc2429. the very first packet // with the stream config info does not have this 00 20. // 3. each fragment of video frame has the appropriate ismacryp // header (= IV in our case since that is all that is supported) // 4. important: the complete frame once all ismacryp streaming // headers are removed still has the header from when it was // encrypted. (i.e IV again in our case). // awv notes. remove the mysterious 00 20. // this is also done to the first fragment of 1st frame which is // the stream config info which does not have 00 20. this will be // accounted for later. dptr += 2; dlen -= 2; // awv notes. remove the IV and save it. // this is also done to the first fragment of 1st frame which is // the stream config info which does not have IV. this will be // accounted for later. // note that IV is saved for each fragment. in the case of the // the first fragment of the first frame, it is gibberish but // it will be set properly when the next fragment arrives. IV = ntohl(*((uint32_t *)(dptr))); dptr += 4; dlen -= 4; uint32_t toadd; // always make sure there are 3 bytes at end... // awv note: I have no idea why this is toadd = dlen + 3; if (toadd + iptr->m_buffer_len > iptr->m_buffer_len_max) { iptr->m_buffer_len_max += toadd + 1024; iptr->m_buffer = (uint8_t *)realloc(iptr->m_buffer, iptr->m_buffer_len_max); } memcpy(iptr->m_buffer + iptr->m_buffer_len, dptr, dlen); iptr->m_buffer_len += dlen; if (rpak->rtp_pak_m != 0) { timetick = iptr->m_vft->rtp_ts_to_msec(iptr->m_ifptr, rtp_ts, ntp_ts, 0); *buffer = iptr->m_buffer; *buflen = iptr->m_buffer_len; if (iptr->frameCount == 1 ) { // this is the first frame so it has the stream config info prepended. // we took off the two mystery bytes and the IV which the stream config // info does not have so we have to account for those. see notes above. // then we have to get rid of the IV which is still on the complete frame. *buffer = &iptr->m_buffer[iptr->mp4SDP->config_binary_len-2-4+4]; *buflen -= (iptr->mp4SDP->config_binary_len-2-4+4); } else { *buffer = &iptr->m_buffer[4]; *buflen -= 4; } ismacrypDecryptSampleRandomAccess(iptr->myEncSID, IV, *buflen, *buffer); //ismacrypDecryptSample(iptr->myEncSID, *buflen, *buffer); ts->msec_timestamp = timetick; ts->timestamp_is_pts = true; return true; } // free and get the next one (iptr->m_vft->free_pak)(rpak); rpak = (iptr->m_vft->get_next_pak)(iptr->m_ifptr, NULL, 1); } while (rpak && rpak->rtp_pak_ts == rtp_ts); } return false;}static void used_bytes_for_frame (rtp_plugin_data_t *pifptr, uint32_t bytes){}static void reset (rtp_plugin_data_t *pifptr){}static void flush_rtp_packets (rtp_plugin_data_t *pifptr){}static bool have_frame (rtp_plugin_data_t *pifptr){ isma_enc_video_rtp_data_t *iptr = (isma_enc_video_rtp_data_t *)pifptr; rtp_packet *rpak, *firstpak; firstpak = rpak = (iptr->m_vft->get_next_pak)(iptr->m_ifptr, NULL, 0); if (firstpak == NULL) return false; if (firstpak->rtp_pak_m != 0) return true; do { rpak = (iptr->m_vft->get_next_pak)(iptr->m_ifptr, rpak, 0); if (rpak == NULL) return false; if (rpak && rpak->rtp_pak_m != 0) return true; } while (rpak != firstpak); return false;}RTP_PLUGIN("enc-mpeg4-generic:video", check, isma_enc_video_rtp_plugin_create, r2429_rtp_destroy, start_next_frame, used_bytes_for_frame, reset, flush_rtp_packets, have_frame, NULL, 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -