2017-02-25 10 views
1

こんにちは私は私の研究に立ち往生しているので、少し助けが必要です。libumのdumepd RTPストリームを読む

問題:gstreamerのどちらか(プログラミングによって)APIまたはコンソールバージョンでavlib(ffmpegの)のいずれかを使用してRTPデータを変換する方法

データ

私は、正確な開始を取得し、ファイル内の各RTPパケットのために停止することができますので、TCP上でRTP/RTCPから来ているRTPダンプを持っています。 H264ビデオストリームダンプです。私は(私は現在やっている)のlibcurlを経由してRTCP/RTPのインターリーブストリーム私は純粋なRTPを消費するffmpegのを使用しようとした

ステータスを取得する必要があるため データは、このやり方でありますrtpをコンソールやプログラミングのいずれかで使用すると、rtsp/rtpセッションビジネス全体がffmpegで「開始」されるように見えます。私はそこに止まったし、当分の間、私はこの道を追求しなかった。私はこれは恋人レベルのRTP APIのような可能性があると思いますff_rtp_parse_packet()私はまっすぐそれを行うには、このlibで新しくなっています。

次にgstreamerがあります。プログラミングをしなくてもやることができますが、当面はRTPダンプを渡す方法がわかりません。

私も入力としてSDPファイルでffplay経由策略の少しを行うとUDPポートにsocatに関する/ NC経由でダンプをストリーミングし、それをリッスンしようとした、いくつかの進展があるように思われますrtpは少なくとも認識されますが、socatにはパケットが欠落しています(おそらくデータがあまりにも速く送信されましたか?)、データは可視化されません。私が使用したときncビデオはひどく間違っていましたが、少なくともそれほど多くのエラーはありませんでした。

データが正しく表示されません。

私はデータを「手作業で」デパケット化することができますが、最終的にビデオと一緒に多重化しなければならないオーディオの第2ストリームも存在するため、アイデアは何らかのライブラリ経由で行うことです。

この問題に対処する方法についてお手伝いします。おかげさまで

答えて

2

最後に、私はこの問題に再び着席する時間があり、最後に私を満足させる解決策を得ました。私はRTPインタリーブされたストリーム(RTPは単一のTCP接続でRTCPとインターリーブされています)を続けました。
Audio(PCM A-Law)とVideo(h.264 Constrained baseline)RTPパケットに逆アセンブルする必要のあるインターリーブされたRTCP/RTPストリームがありました。
RTPデータを含むRTSPストリームの分解については、ここにはrfc2326と記載されています。
H264のデパケート化は、ここではrfc6184と記載されています.PCM A-Lawの場合、フレームはRTPの生のオーディオになっているので、デパケタイズは必要ありません。

次のステップは、ストリームごとに適切なPTS(またはプレゼンテーションタイムスタンプ)を計算することでしたが、ちょっと面倒でしたが、最後にLive555コードが (RTP lipsync synchronization参照)に役立ちました。
最後のタスクは、PCM alawをサポートするコンテナにmuxすることでした。私はffmpegのavlibrariesを使用しました。
インターネット上では多くの例がありますが、多くは古くなっています(ffmpegはAPIの変更領域では非常に「動的」です)。私は最終的に私のために実際に働いていたものを投稿しています:

設定部:

#include <libavcodec/avcodec.h> 
#include <libavformat/avformat.h> 
#include "libavutil/intreadwrite.h" 
#include "libavutil/mathematics.h" 

AVFormatContext *formatContext; 
AVOutputFormat *outputFormat; 
AVStream   *video_st; 
AVStream   *audio_st; 
AVCodec   *av_encode_codec = NULL; 
AVCodec   *av_audio_encode_codec = NULL; 
AVCodecContext *av_video_encode_codec_ctx = NULL; 
AVCodecContext *av_audio_encode_codec_ctx = NULL; 


av_register_all(); 
av_log_set_level(AV_LOG_TRACE); 
outputFormat = av_guess_format(NULL, pu8outFileName, NULL); 
outputFormat->video_codec = AV_CODEC_ID_H264; 

av_encode_codec = avcodec_find_encoder(AV_CODEC_ID_H264); 
av_audio_encode_codec = avcodec_find_encoder(AV_CODEC_ID_PCM_ALAW); 
avformat_alloc_output_context2(&formatContext, NULL, NULL, pu8outFileName); 
formatContext->oformat = outputFormat; 
strcpy(formatContext->filename, pu8outFileName); 
outputFormat->audio_codec = AV_CODEC_ID_PCM_ALAW; 

av_video_encode_codec_ctx = avcodec_alloc_context3(av_encode_codec); 
av_audio_encode_codec_ctx = avcodec_alloc_context3(av_audio_encode_codec); 

av_video_encode_codec_ctx->codec_id = outputFormat->video_codec; 
av_video_encode_codec_ctx->codec_type = AVMEDIA_TYPE_VIDEO; 
av_video_encode_codec_ctx->bit_rate = 4000; 
av_video_encode_codec_ctx->width = u32width; 
av_video_encode_codec_ctx->height = u32height; 
av_video_encode_codec_ctx->time_base = (AVRational){ 1, u8fps }; 
av_video_encode_codec_ctx->max_b_frames = 0; 
av_video_encode_codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P; 

av_audio_encode_codec_ctx->sample_fmt = AV_SAMPLE_FMT_S16; 
av_audio_encode_codec_ctx->codec_id = AV_CODEC_ID_PCM_ALAW; 
av_audio_encode_codec_ctx->codec_type = AVMEDIA_TYPE_AUDIO; 
av_audio_encode_codec_ctx->sample_rate = 8000; 
av_audio_encode_codec_ctx->channels = 1; 
av_audio_encode_codec_ctx->time_base = (AVRational){ 1, u8fps }; 
av_audio_encode_codec_ctx->channel_layout = AV_CH_LAYOUT_MONO; 

video_st = avformat_new_stream(formatContext, av_encode_codec); 
audio_st = avformat_new_stream(formatContext, av_audio_encode_codec); 
audio_st->index = 1; 
video_st->avg_frame_rate = (AVRational){ 90000, 90000/u8fps }; 
av_stream_set_r_frame_rate(video_st, (AVRational){ 90000, 90000/u8fps }); 

ビデオのためのパケットは次のように書かれている:

uint8_t *pu8framePtr = video_frame; 
AVPacket pkt = { 0 }; 
av_init_packet(&pkt); 
if (0x65 == pu8framePtr[4] || 0x67 == pu8framePtr[4] || 0x68 == pu8framePtr[4]) 
{ 
    pkt.flags = AV_PKT_FLAG_KEY; 
} 

pkt.data = (uint8_t *)pu8framePtr; 
pkt.size = u32LastFrameSize; 

pkt.pts = av_rescale_q(s_video_sync.fSyncTime.tv_sec * 1000000 + s_video_sync.fSyncTime.tv_usec, (AVRational){ 1, 1000000 }, video_st->time_base); 
pkt.dts = pkt.pts; 
pkt.stream_index = video_st->index; 
av_interleaved_write_frame(formatContext, &pkt); 
av_packet_unref(&pkt); 

と、このようなオーディオ用:

AVPacket pkt = { 0 }; 
av_init_packet(&pkt); 
pkt.flags = AV_PKT_FLAG_KEY; 
pkt.data = (uint8_t *)pu8framePtr; 
pkt.size = u32AudioDataLen; 

pkt.pts = av_rescale_q(s_audio_sync.fSyncTime.tv_sec * 1000000 + s_audio_sync.fSyncTime.tv_usec, (AVRational){ 1, 1000000 }, audio_st->time_base); 
pkt.dts = pkt.pts; 
pkt.stream_index = audio_st->index; 
if (u8FirstIFrameFound) {av_interleaved_write_frame(formatContext, &pkt);} 
av_packet_unref(&pkt) 

、最後にいくつかのdeinits:

av_write_trailer(formatContext); 
av_dump_format(formatContext, 0, pu8outFileName, 1); 
avcodec_free_context(&av_video_encode_codec_ctx); 
avcodec_free_context(&av_audio_encode_codec_ctx); 
avio_closep(&formatContext->pb); 
avformat_free_context(formatContext); 
+0

ない私は理解しますが行う場合は、ファイルのRTPパケットから読み取られ、その後、あなたはFEADと確信してあなたのためにフレームをデコードするためにそれとffmpeg?私はRTPストリームをキャプチャしてffmpegにデコードする(プログラム的に)必要があるだけでなく、ffmpegの使用方法も見つけられないという非常に似た問題があります。ソリューションからより多くのコードを共有できますか?御時間ありがとうございます。 – stviper

+0

さて、私はファイルからRTPデータを読んだり(各RTPパケットの開始と長さを知っているインターリーブされたtcpデータなので)、ビットレートと解像度に応じてh.264をh.264フレームにデパケット化することがあります。 RTPパケット。私は申し訳ありませんデコードしない、私はコンテナにすでにエンコードされたデータをmuxだけです。 –

関連する問題