Created
August 21, 2018 06:11
-
-
Save moonpfe/5f45f72bb5090f2da8aac2b7f4f556bd to your computer and use it in GitHub Desktop.
extract codec extradata size if it is need
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/edc-buf.c b/edc-buf.c | |
index 1914e60c..65ba1e14 100644 | |
--- a/edc-buf.c | |
+++ b/edc-buf.c | |
@@ -56,6 +56,7 @@ edc_buf_new (guint len) | |
buf->flags = 0; | |
buf->width = 0; | |
buf->height = 0; | |
+ buf->codec_extra_len = 0; | |
buf->timestamp = 0; | |
buf->extra = NULL; | |
diff --git a/edc-buf.h b/edc-buf.h | |
index e3b4e1eb..b2f26ede 100644 | |
--- a/edc-buf.h | |
+++ b/edc-buf.h | |
@@ -63,6 +63,7 @@ struct _EdcBuf | |
uint16_t width; | |
uint16_t height; | |
+ int codec_extra_len; | |
void *extra; | |
diff --git a/edc-link-impl.h b/edc-link-impl.h | |
index e32602f6..69ade373 100644 | |
--- a/edc-link-impl.h | |
+++ b/edc-link-impl.h | |
@@ -145,6 +145,8 @@ struct _EdcLink | |
int shutdown_flag; | |
+ int video_codec_extra_len; | |
+ | |
unsigned int check_alive_mode : 1; | |
unsigned int shutdown_by_app : 1; | |
unsigned int video_only : 1; | |
diff --git a/edc-link.c b/edc-link.c | |
index d27f8877..fd6be3ae 100644 | |
--- a/edc-link.c | |
+++ b/edc-link.c | |
@@ -9,10 +9,12 @@ | |
#include "edc-link.h" | |
#include "edc-link-impl.h" | |
#include "edc-atomic.h" | |
+#include "edc-codec.h" | |
#include "edc-manager.h" | |
#include "edc-util.h" | |
#include "edc-key.h" | |
#include "edc-event.h" | |
+#include <libavformat/avformat.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
@@ -321,6 +323,8 @@ edc_link_initialize (EdcLink *l, | |
l->send_frame_fast = 0; | |
l->buffering_size = 0; | |
+ l->video_codec_extra_len = -1; | |
+ | |
l->connect_params = edc_map_new (64); | |
for (i = 0; i < EDC_ATTR_MAX; i++) | |
@@ -430,6 +434,8 @@ edc_link_set_state (EdcLink *l, EdcState state) | |
{ | |
int i; | |
+ l->video_codec_extra_len = -1; | |
+ | |
edc_link_flush_all_buffering_queue (l); | |
if (!l->check_alive_mode && | |
@@ -672,6 +678,115 @@ edc_link_notify_frame_timeout (gpointer data) | |
return FALSE; | |
} | |
+static int | |
+edc_link_extract_extradata (EdcLink *l, | |
+ EdcBuf *frame) | |
+{ | |
+ AVBSFContext *bsf; | |
+ const AVBitStreamFilter *f; | |
+ const enum AVCodecID *ids; | |
+ AVPacket *dst_pkt; | |
+ int avcodec_id; | |
+ int found; | |
+ int ret; | |
+ AVPacket pkt; | |
+ AVPacket *pkt_ref; | |
+ int size; | |
+ | |
+ size = 0; | |
+ | |
+ f = av_bsf_get_by_name ("extract_extradata"); | |
+ if (!f || !f->codec_ids) | |
+ return 0; | |
+ | |
+ avcodec_id = edc_codec_lookup_avcodec_id (frame->codec_id); | |
+ | |
+ found = 0; | |
+ for (ids = f->codec_ids; *ids != AV_CODEC_ID_NONE; ids++) | |
+ { | |
+ if (*ids == avcodec_id) | |
+ { | |
+ found = 1; | |
+ break; | |
+ } | |
+ } | |
+ | |
+ if (!found) | |
+ return 0; | |
+ | |
+ bsf = NULL; | |
+ ret = av_bsf_alloc (f, &bsf); | |
+ if (ret < 0) | |
+ return 0; | |
+ | |
+ bsf->par_in->codec_id = avcodec_id; | |
+ ret = av_bsf_init (bsf); | |
+ if (ret < 0) | |
+ { | |
+ av_bsf_free (&bsf); | |
+ | |
+ return 0; | |
+ } | |
+ | |
+ dst_pkt = av_packet_alloc (); | |
+ pkt_ref = dst_pkt; | |
+ | |
+ av_init_packet (&pkt); | |
+ pkt.data = (uint8_t *) frame->data; | |
+ pkt.size = frame->len; | |
+ if (frame->flags & EDC_BUF_FLAG_KEY_FRAME) | |
+ pkt.flags |= AV_PKT_FLAG_KEY; | |
+ | |
+ ret = av_packet_ref (pkt_ref, &pkt); | |
+ if (ret < 0) | |
+ goto end_of_extract_extradata; | |
+ | |
+ ret = av_bsf_send_packet (bsf, pkt_ref); | |
+ if (ret < 0) | |
+ { | |
+ av_packet_unref (pkt_ref); | |
+ | |
+ goto end_of_extract_extradata; | |
+ } | |
+ | |
+ ret = 0; | |
+ while (ret >= 0) | |
+ { | |
+ uint8_t *extradata; | |
+ int extradata_size; | |
+ | |
+ ret = av_bsf_receive_packet (bsf, pkt_ref); | |
+ if (ret < 0) | |
+ { | |
+ if (ret != AVERROR (EAGAIN) && ret != AVERROR_EOF) | |
+ break; | |
+ | |
+ continue; | |
+ } | |
+ | |
+ extradata = av_packet_get_side_data (pkt_ref, | |
+ AV_PKT_DATA_NEW_EXTRADATA, | |
+ &extradata_size); | |
+ if (extradata && extradata_size > 0) | |
+ { | |
+ size = extradata_size; | |
+ | |
+ av_packet_unref (pkt_ref); | |
+ | |
+ break; | |
+ } | |
+ | |
+ av_packet_unref (pkt_ref); | |
+ } | |
+ | |
+end_of_extract_extradata: | |
+ | |
+ av_bsf_free (&bsf); | |
+ av_packet_free (&dst_pkt); | |
+ | |
+ return size; | |
+} | |
+ | |
void | |
edc_link_notify_frame (EdcLink *l, EdcBuf *frame) | |
{ | |
@@ -723,6 +838,17 @@ edc_link_notify_frame (EdcLink *l, EdcBuf *frame) | |
/* Set the timestamp of the frame only if it's not set yet. */ | |
if (!frame->timestamp) | |
frame->timestamp = edc_get_real_time (); | |
+ | |
+ if (type == EDC_CHANNEL_VIDEO && | |
+ frame->flags & EDC_BUF_FLAG_KEY_FRAME && | |
+ frame->codec_extra_len == 0) | |
+ { | |
+ if (l->video_codec_extra_len < 0) | |
+ l->video_codec_extra_len = edc_link_extract_extradata (l, frame); | |
+ | |
+ frame->codec_extra_len = l->video_codec_extra_len; | |
+ } | |
+ | |
if (l->buffering_size <= 0 || type != EDC_CHANNEL_VIDEO) | |
{ | |
edc_link_notify_frame_real (l, frame); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment