Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • videolan/vlc
  • chouquette/vlc
  • bakiewicz.marek122/vlc
  • devnexen/vlc
  • rohanrajpal/vlc
  • blurrrb/vlc
  • gsoc/gsoc2019/darkapex/vlc
  • b1ue/vlc
  • fkuehne/vlc
  • magsoft/vlc
  • chub/vlc
  • cramiro9/vlc
  • robUx4/vlc
  • rom1v/vlc
  • akshayaky/vlc
  • tmk907/vlc
  • akymaster/vlc
  • govind.sharma/vlc
  • psilokos/vlc
  • xjbeta/vlc
  • jahan/vlc
  • 1480c1/vlc
  • amanchande/vlc
  • aaqib/vlc
  • rist/vlc
  • apol/vlc
  • mindfreeze/vlc
  • alexandre-janniaux/vlc
  • sandsmark/vlc
  • jagannatharjun/vlc
  • gsoc/gsoc2020/matiaslgonzalez/vlc
  • gsoc/gsoc2020/jagannatharjun/vlc
  • mstorsjo/vlc
  • gsoc/gsoc2020/vedenta/vlc
  • gsoc/gsoc2020/arnav-ishaan/vlc
  • gsoc/gsoc2020/andreduong/vlc
  • fuzun/vlc
  • gsoc/gsoc2020/vatsin/vlc
  • gsoc/gsoc2020/sagid/vlc
  • yaron/vlc
  • Phoenix/vlc
  • Garf/vlc
  • ePiratWorkarounds/vlc
  • tguillem/vlc
  • jnqnfe/vlc
  • mdc/vlc
  • Vedaa/vlc
  • rasa/vlc
  • quink/vlc
  • yealo/vlc
  • aleksey_ak/vlc
  • ePirat/vlc
  • ilya.yanok/vlc
  • asenat/vlc
  • m/vlc
  • bunjee/vlc
  • BLumia/vlc
  • sagudev/vlc
  • hamedmonji30/vlc
  • nullgemm/vlc
  • DivyamAhuja/vlc
  • thesamesam/vlc
  • dag7/vlc
  • snehil101/vlc
  • haasn/vlc
  • jbk/vlc
  • ValZapod/vlc
  • mfkl/vlc
  • WangChuan/vlc
  • core1024/vlc
  • GhostVaibhav/vlc
  • dfuhrmann/vlc
  • davide.prade/vlc
  • tmatth/vlc
  • Courmisch/vlc
  • zouya/vlc
  • hpi/vlc
  • EwoutH/vlc
  • aleung27/vlc
  • hengwu0/vlc
  • saladin/vlc
  • ashuio/vlc
  • richselwood/vlc
  • verma16Ayush/vlc
  • chemicalflash/vlc
  • PoignardAzur/vlc
  • huangjieNT/vlc
  • Blake-Haydon/vlc
  • AnuthaDev/vlc
  • gsoc/gsoc2021/mpd/vlc
  • nicolas_lequec/vlc
  • sambassaly/vlc
  • thresh/vlc
  • bonniegong/vlc
  • myaashish/vlc
  • stavros.vagionitis/vlc
  • ileoo/vlc
  • louis-santucci/vlc
  • cchristiansen/vlc
  • sabyasachi07/vlc
  • AbduAmeen/vlc
  • ashishb0410/vlc
  • urbanhusky/vlc
  • davidepietrasanta/vlc
  • riksleutelstad/vlc
  • jeremyVignelles/vlc
  • komh/vlc
  • iamjithinjohn/vlc
  • JohannesKauffmann/vlc2
  • kunglao/vlc
  • natzberg/vlc
  • jill/vlc
  • cwendling/vlc
  • adufou/vlc
  • ErwanAirone/vlc
  • HasinduDilshan10/vlc
  • vagrantc/vlc
  • rafiv/macos-bigsur-icon
  • Aymeriic/vlc
  • saranshg20/vlc
  • metzlove24/vlc
  • linkfanel/vlc
  • Ds886/vlc
  • metehan-arslan/vlc
  • Skantes/vlc
  • kgsandundananjaya96/vlc
  • mitchcapper/vlc
  • advaitgupta/vlc
  • StefanBruens/vlc
  • ratajs/vlc
  • T.M.F.B.3761/vlc
  • m222059/vlc
  • casemerrick/vlc
  • joshuaword2alt/vlc
  • sjwaddy/vlc
  • dima/vlc
  • Ybalrid/vlc
  • umxprime/vlc
  • eschmidt/vlc
  • vannieuwenhuysenmichelle/vlc
  • badcf00d/vlc
  • wesinator/vlc
  • louis/vlc
  • xqq/vlc
  • EmperorYP7/vlc
  • NicoLiam/vlc
  • loveleen/vlc
  • rofferom/vlc
  • rbultje/vlc
  • TheUnamed/vlc
  • pratiksharma341/vlc
  • Saurab17/vlc
  • purist.coder/vlc
  • Shuicheng/vlc
  • mdrrubel292/vlc
  • silverbleu00/vlc
  • metif12/vlc
  • asher-m/vlc
  • jeffk/vlc
  • Brandonbr1/vlc
  • beautyyuyanli/vlc
  • rego21/vlc
  • muyangren907/vlc
  • collectionbylawrencejason/vlc
  • evelez/vlc
  • GSMgeeth/vlc
  • Oneric/vlc
  • TJ5/vlc
  • XuanTung95/vlc
  • darrenjenny21/vlc
  • Trenly/vlc
  • RockyTDR/vlc
  • mjakubowski/vlc
  • caprica/vlc
  • ForteFrankie/vlc
  • seannamiller19/vlc
  • junlon2006/vlc
  • kiwiren6666/vlc
  • iuseiphonexs/vlc
  • fenngtun/vlc
  • Rajdutt999/vlc
  • typx/vlc
  • leon.vitanos/vlc
  • robertogarci0938/vlc
  • gsoc/gsoc2022/luc65r/vlc-mpd
  • skeller/vlc
  • MCJack123/vlc
  • luc65r/vlc-mpd
  • popov895/vlc
  • claucambra/vlc
  • brad/vlc
  • matthewmurua88/vlc
  • Tomas8874/vlc
  • philenotfound/vlc
  • makita-do3/vlc
  • LZXCorp/vlc
  • mar0x/vlc
  • senojetkennedy0102/vlc
  • shaneb243/vlc
  • ahmadbader/vlc
  • rajduttcse26/vlc-audio-filters
  • Juniorzito8415/vlc
  • achernyakov/vlc
  • lucasjetgroup/vlc
  • pupdoggy666/vlc
  • gmde9363/vlc
  • alexnwayne/vlc
  • bahareebrahimi781/vlc
  • hamad633666/vlc
  • umghof3112/vlc
  • joe0199771874/vlc
  • Octocats66666666/vlc
  • jjm_223/vlc
  • btech10110.19/vlc
  • sunnykfc028/vlc-audio-filters
  • loic/vlc
  • nguyenminhducmx1/vlc
  • JanekKrueger/vlc
  • bstubbington2/vlc
  • rcombs/vlc
  • Ordissimo/vlc
  • king7532/vlc
  • noobsauce101/vlc
  • schong0525/vlc
  • myQwil/vlc
  • apisbg91/vlc
  • geeboy0101017/vlc
  • kim.faughey/vlc
  • nurupo/vlc
  • yyusea/vlc
  • 0711235879.khco/vlc
  • ialo/vlc
  • iloveyeye2/vlc
  • gdtdftdqtd/vlc
  • leandroconsiglio/vlc
  • AndyHTML2012/vlc
  • ncz/vlc
  • lucenticus/vlc
  • knr1931/vlc
  • kjoonlee/vlc
  • chandrakant100/vlc-qt
  • johge42/vlc
  • polter/vlc
  • hexchain/vlc
  • Tushwrld/vlc
  • mztea928/vlc
  • jbelloncastro/vlc
  • alvinhochun/vlc
  • ghostpiratecrow/vlc
  • ujjwaltwitx/vlc
  • alexsonarin06/vlc
  • adrianbon76/vlc
  • altsod/vlc
  • damien.lucas44/vlc
  • dmytrivtaisa/vlc
  • utk202/vlc
  • aaxhrj/vlc
  • thomas.hermes/vlc
  • structurenewworldorder/vlc
  • slomo/vlc
  • wantlamy/vlc
  • musc.o3cminc/vlc
  • thebarshablog/vlc
  • kerrick/vlc
  • kratos142518/vlc
  • leogps/vlc
  • vacantron/vlc
  • luna_koly/vlc
  • Ratio2/vlc
  • anuoshemohammad/vlc
  • apsun/vlc
  • aaa1115910/vlc
  • alimotmoyo/vlc
  • Ambossmann/vlc
  • Sam-LearnsToCode/vlc
  • Chilledheart/vlc
  • Labnann/vlc
  • ktcoooot1/vlc
  • mohit-marathe/vlc
  • johnddx/vlc
  • manstabuk/vlc
  • Omar-ahmed314/vlc
  • vineethkm/vlc
  • 9Enemi86/vlc
  • radoslav.m.panteleev/vlc
  • ashishami2002/vlc
  • Corbax/vlc
  • firnasahmed/vlc
  • pelayarmalam4/vlc
  • c0ff330k/vlc
  • shikhindahikar/vlc
  • l342723951/vlc
  • christianschwandner/vlc
  • douniwan5788/vlc
  • 7damian7/vlc
  • ferdnyc/vlc
  • f.ales1/vlc
  • pandagby/vlc
  • BaaBaa/vlc
  • jewe37/vlc
  • w00drow/vlc
  • russelltg/vlc
  • ironicallygod/vlc
  • soumyaDghosh/vlc
  • linzihao1999/vlc
  • deyayush6/vlc
  • mibi88/vlc
  • newabdallah10/vlc
  • jhorbincolombia/vlc
  • rimvihaqueshupto/vlc
  • andrewkhon98/vlc
  • fab78/vlc
  • lapaz17/vlc
  • amanna13/vlc
  • mdakram28/vlc
  • 07jw1980/vlc
  • sohamgupta/vlc
  • Eson-Jia1/vlc
  • Sumou/vlc
  • vikram-kangotra/vlc
  • chalice191/vlc
  • olivercalder/vlc
  • aaasg4001/vlc
  • zipdox/vlc
  • kwizart/vlc
  • Dragon-S/vlc
  • jdemeule/vlc
  • gabriel_lt/vlc
  • locutusofborg/vlc
  • sammirata/vlc-librist
  • another/vlc
  • Benjamin_Loison/vlc
  • ahmedmoselhi/vlc
  • petergaal/vlc
  • huynhsontung/vlc
  • dariusmihut/vlc
  • tvermaashutosh/vlc
  • buti/vlc
  • Niram7777/vlc
  • rohan-here/vlc
  • balaji-sivasakthi/vlc
  • rlindner81/vlc
  • Kakadus/vlc
  • djain/vlc
  • ABBurmeister/vlc
  • craighuggins/vlc
  • orbea/vlc
  • maxos/vlc
  • aakarshmj/vlc
  • kblaschke/vlc
  • ankitm/vlc
  • advait-0/vlc
  • mohak2003/vlc
  • yselkowitz/vlc
  • AZM999/vlc-azm
  • andrey.turkin/vlc
  • Disha-Baghel/vlc
  • nowrep/vlc
  • Apeng/vlc
  • Choucroute_melba/vlc
  • autra/vlc
  • eclipseo/vlc
  • fhuber/vlc
  • olafhering/vlc
  • sdasda7777/vlc
  • 1div0/vlc
  • skosnits/vlc-extended-playlist-support
  • dnicolson/vlc
  • Timshel/vlc
  • octopols/vlc
  • MangalK/vlc
  • nima64/vlc
  • misawai/vlc
  • Alexander-Wilms/vlc
  • Maxime2/vlc-fork-for-visualizer
  • ww/vlc
  • jeske/vlc
  • sgross-emlix/vlc
  • morenonatural/vlc
  • freakingLovesVLC/vlc
  • borisgolovnev/vlc
  • mpromonet/vlc
  • diogo.simao-marques/vlc
  • masstock/vlc
  • pratikpatel8982/vlc
  • hugok79/vlc
  • longervision/vlc
  • abhiudaysurya/vlc
  • rishabhgarg/vlc
  • tumic/vlc
  • cart/vlc
  • shubham442/vlc
  • Aditya692005/vlc
  • sammirata/vlc4
  • syrykh/vlc
  • Vvorcun/macos-new-icon
  • AyaanshC/vlc
  • nasso/vlc
  • Quark/vlc
  • sebastinas/vlc
  • rhstone/vlc
  • talregev/vlc
  • Managor/vlc
  • abdsaber000/vlc
  • falbrechtskirchinger/vlc
  • b.sullender/vlc
  • hulxv/vlc
  • zyad-ayad/vlc
408 results
Show changes
Commits on Source (5)
......@@ -41,6 +41,7 @@ rtpparse_LTLIBRARIES = \
librtp_pcm_plugin.la \
librtp_raw_plugin.la \
librtp_h264_plugin.la \
librtp_h265_plugin.la \
librtp_opus_plugin.la \
librtp_xiph_plugin.la
......@@ -52,7 +53,9 @@ librtp_pcm_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/access/rtp
librtp_raw_plugin_la_SOURCES = access/rtp/raw.c
librtp_h264_plugin_la_SOURCES = access/rtp/h264.c
librtp_h264_plugin_la_SOURCES = access/rtp/h264.c access/rtp/h26x.h
librtp_h265_plugin_la_SOURCES = access/rtp/h265.c access/rtp/h26x.h
librtp_opus_plugin_la_SOURCES = access/rtp/opus.c
......
......@@ -24,96 +24,21 @@
#include <assert.h>
#include <vlc_common.h>
#include "h26x.h"
#include <vlc_plugin.h>
#include <vlc_block.h>
#include <vlc_strings.h>
#include <vlc_codec.h>
#include "rtp.h"
#include "sdp.h"
struct rtp_h26x_sys
struct h264_pt_opaque
{
vlc_tick_t pts;
block_t **pp_packets_next;
block_t *p_packets;
block_t *xps;
struct vlc_rtp_es *es;
block_t *sdpxps;
vlc_object_t *obj;
};
static void rtp_h26x_clear(struct rtp_h26x_sys *sys)
{
block_ChainRelease(sys->p_packets);
if(sys->xps)
block_Release(sys->xps);
}
static void rtp_h26x_init(struct rtp_h26x_sys *sys)
{
sys->pts = VLC_TICK_INVALID;
sys->p_packets = NULL;
sys->pp_packets_next = &sys->p_packets;
sys->xps = NULL;
sys->es = NULL;
}
static const uint8_t annexbheader[] = { 0, 0, 0, 1 };
static block_t * h26x_wrap_prefix(block_t *block, bool b_annexb)
{
block = block_Realloc(block, 4, block->i_buffer);
if(block)
{
if(b_annexb)
memcpy(block->p_buffer, annexbheader, 4);
else
SetDWBE(block->p_buffer, block->i_buffer - 4);
}
return block;
}
static void h26x_extractbase64xps(const char *psz64,
const char *pszend,
void(*pf_output)(void *, uint8_t *, size_t),
void *outputsys)
{
do
{
psz64 += strspn(psz64, " ");
uint8_t *xps = NULL;
size_t xpssz = vlc_b64_decode_binary(&xps, psz64);
pf_output(outputsys, xps, xpssz);
psz64 = strchr(psz64, ',');
if(psz64)
++psz64;
} while(psz64 && *psz64 && psz64 < pszend);
}
static void h264_add_xps(void *priv, uint8_t *xps, size_t xpssz)
{
block_t *b = block_heap_Alloc(xps, xpssz);
if(!b || !(b = h26x_wrap_prefix(b, true)))
return;
block_t ***ppp_append = priv;
**ppp_append = b;
*ppp_append = &((**ppp_append)->p_next);
}
static block_t * h264_fillextradata (const char *psz)
{
block_t *xps = NULL;
block_t **pxps = &xps;
h26x_extractbase64xps(psz, strchr(psz, ';'), h264_add_xps, &pxps);
if(xps)
xps = block_ChainGather(xps);
return xps;
}
static void *rtp_h264_init(struct vlc_rtp_pt *pt)
{
block_t *sdpparams = pt->opaque;
struct h264_pt_opaque *opaque = pt->opaque;
block_t *sdpparams = opaque->sdpxps;
struct rtp_h26x_sys *sys = malloc(sizeof(*sys));
if(!sys)
return NULL;
......@@ -123,7 +48,14 @@ static void *rtp_h264_init(struct vlc_rtp_pt *pt)
es_format_Init (&fmt, VIDEO_ES, VLC_CODEC_H264);
fmt.b_packetized = false;
sys->es = vlc_rtp_pt_request_es(pt, &fmt);
sys->p_packetizer = demux_PacketizerNew(opaque->obj, &fmt, "rtp packetizer");
if(!sys->p_packetizer)
{
free(sys);
return NULL;
}
sys->es = vlc_rtp_pt_request_es(pt, &sys->p_packetizer->fmt_out);
if(sdpparams)
sys->xps = block_Duplicate(sdpparams);
......@@ -136,6 +68,8 @@ static void rtp_h264_destroy(struct vlc_rtp_pt *pt, void *data)
struct rtp_h26x_sys *sys = data;
if(sys)
{
if(sys->p_packetizer)
demux_PacketizerDestroy(sys->p_packetizer);
vlc_rtp_es_destroy(sys->es);
rtp_h26x_clear(sys);
free(sys);
......@@ -226,41 +160,6 @@ static block_t * h264_chainsplit_MTAP(block_t *block, bool b_24ext,
return p_chain;
}
static void h26x_output(struct rtp_h26x_sys *sys,
block_t *block,
vlc_tick_t pts, bool pcr, bool au_end)
{
// if(pcr)
// es_out_SetPCR(out, pts);
if(!block)
return;
if(sys->xps)
{
block_t *xps = sys->xps;
sys->xps = NULL;
h26x_output(sys, xps, pts, pcr, false);
}
block->i_pts = pts;
block->i_dts = VLC_TICK_INVALID; /* RTP does not specify this */
if(au_end)
block->i_flags |= BLOCK_FLAG_AU_END;
vlc_rtp_es_send(sys->es, block);
}
static void h26x_output_blocks(struct rtp_h26x_sys *sys, bool b_annexb)
{
if(!sys->p_packets)
return;
block_t *out = block_ChainGather(sys->p_packets);
sys->p_packets = NULL;
sys->pp_packets_next = &sys->p_packets;
out = h26x_wrap_prefix(out, b_annexb);
h26x_output(sys, out, sys->pts, true, false);
}
static void rtp_h264_decode(struct vlc_rtp_pt *pt, void *data, block_t *block,
const struct vlc_rtp_pktinfo *restrict info)
{
......@@ -354,9 +253,10 @@ drop:
static void rtp_h264_release(struct vlc_rtp_pt *pt)
{
block_t *sdpparams = pt->opaque;
if(sdpparams)
block_Release(sdpparams);
struct h264_pt_opaque *opaque = pt->opaque;
if(opaque->sdpxps)
block_Release(opaque->sdpxps);
free(opaque);
}
static const struct vlc_rtp_pt_operations rtp_h264_ops = {
......@@ -380,12 +280,18 @@ static int rtp_h264_open(vlc_object_t *obj, struct vlc_rtp_pt *pt,
else
return VLC_ENOTSUP;
pt->opaque = NULL;
struct h264_pt_opaque *opaque = calloc(1, sizeof(*opaque));
if(!opaque)
return VLC_ENOMEM;
pt->opaque = opaque;
opaque->obj = obj;
if(desc->parameters)
{
psz = strstr(desc->parameters, "sprop-parameter-sets=");
if(psz)
pt->opaque = h264_fillextradata(psz + 21);
opaque->sdpxps = h26x_fillextradata(psz + 21);
}
return VLC_SUCCESS;
......
/**
* @file h265.c
*/
/*****************************************************************************
* Copyright (C) 2022 VideoLabs, VLC authors and VideoLAN
*
* This library 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.
*
* This library 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <assert.h>
#include "h26x.h"
#define FLAG_DONL 1
#include <vlc_plugin.h>
#include <vlc_codec.h>
struct h265_pt_opaque
{
block_t *sdpxps;
bool b_donl;
vlc_object_t *obj;
};
static void *rtp_h265_init(struct vlc_rtp_pt *pt)
{
struct h265_pt_opaque *opaque = pt->opaque;
struct rtp_h26x_sys *sys = malloc(sizeof(*sys));
if(!sys)
return NULL;
rtp_h26x_init(sys);
es_format_t fmt;
es_format_Init (&fmt, VIDEO_ES, VLC_CODEC_HEVC);
fmt.b_packetized = false;
sys->p_packetizer = demux_PacketizerNew(opaque->obj, &fmt, "rtp packetizer");
if(!sys->p_packetizer)
{
free(sys);
return NULL;
}
sys->es = vlc_rtp_pt_request_es(pt, &sys->p_packetizer->fmt_out);
if(opaque->sdpxps)
sys->xps = block_Duplicate(opaque->sdpxps);
if(opaque->b_donl)
sys->flags = FLAG_DONL;
return sys;
}
static void rtp_h265_destroy(struct vlc_rtp_pt *pt, void *data)
{
VLC_UNUSED(pt);
struct rtp_h26x_sys *sys = data;
if(sys)
{
if(sys->p_packetizer)
demux_PacketizerDestroy(sys->p_packetizer);
vlc_rtp_es_destroy(sys->es);
rtp_h26x_clear(sys);
free(sys);
}
}
static block_t * h265_deaggregate_AP(block_t *block, bool b_donl, bool b_annexb)
{
size_t total = 0;
if(b_donl)
{
if(block->i_buffer < 4)
{
block_Release(block);
return NULL;
}
/* Skip Half DONL, so we always get an extra 1 byte extra prefix */
block->p_buffer += 1;
block->i_buffer -= 1;
}
const uint8_t *p = block->p_buffer;
size_t sz = block->i_buffer;
/* first pass, compute final size */
while(sz > (b_donl ? 2 : 1))
{
/* skip 1/2 DONL or DOND here */
if(b_donl)
{
p += 1;
sz -= 1;
}
size_t nalsz = GetWBE(p);
if(nalsz + 2 > sz)
{
vlc_assert_unreachable();
break;
}
total += nalsz + 4;
sz -= (nalsz + 2);
p += (nalsz + 2);
}
block_t *newblock = block_Alloc(total);
if(newblock)
{
uint8_t *dst = newblock->p_buffer;
p = block->p_buffer;
sz = block->i_buffer;
while(sz > (b_donl ? 2 : 1))
{
/* skip 1/2 DONL or DOND here */
if(b_donl)
{
p += 1;
sz -= 1;
}
size_t nalsz = GetWBE(p);
if(nalsz + 2 > sz)
break;
if(b_annexb)
memcpy(dst, annexbheader, 4);
else
SetDWBE(dst, nalsz);
dst += 4;
memcpy(dst, p + 2, nalsz);
dst += nalsz;
sz -= (nalsz + 2);
p += (nalsz + 2);
}
block_Release(block);
block = newblock;
}
else
{
block_Release(block);
block = NULL;
}
return block;
}
static void rtp_h265_decode (struct vlc_rtp_pt *pt, void *data, block_t *block,
const struct vlc_rtp_pktinfo *restrict info)
{
VLC_UNUSED(pt);
struct rtp_h26x_sys *sys = data;
const bool b_au_end = info->m;
if(block->i_buffer < 2)
{
block_Release(block);
return;
}
const uint8_t type = (block->p_buffer[0] & 0x7E) >> 1;
const uint8_t layerID = ((block->p_buffer[0] & 0x01) << 5) | (block->p_buffer[1] >> 3);
const uint8_t temporalID = block->p_buffer[1] & 0x07;
const vlc_tick_t pts = block->i_pts;
switch(type)
{
case 48: /* AP */
/* end unfinished aggregates */
h26x_output_blocks(sys, true);
/* skip header */
block->i_buffer -= 2;
block->p_buffer += 2;
block = h265_deaggregate_AP(block, sys->flags & FLAG_DONL, true);
h26x_output(sys, block, pts, true, b_au_end);
break;
case 49: /* FU */
{
if(block->i_buffer < ((sys->flags & FLAG_DONL) ? 6 : 4))
goto drop;
const bool start = block->p_buffer[2] & 0x80;
const bool end = block->p_buffer[2] & 0x40;
const uint8_t futype = block->p_buffer[2] & 0x3f;
/* skip FU header and rebuild NAL header */
if(start)
{
/* end unfinished aggregates */
h26x_output_blocks(sys, true);
/* rebuild NAL header, overwriting last PAYL[DON]FU 2 bytes */
if(sys->flags & FLAG_DONL)
{
block->i_buffer -= 3;
block->p_buffer += 3;
}
else
{
block->i_buffer -= 1;
block->p_buffer += 1;
}
block->p_buffer[0] = (futype << 1) | (layerID >> 5);
block->p_buffer[1] = (layerID << 3) | temporalID;
sys->pts = pts;
}
else /* trail data */
{
block->i_buffer -= (sys->flags & FLAG_DONL) ? 5 : 3;
block->p_buffer += (sys->flags & FLAG_DONL) ? 5 : 3;
}
block_ChainLastAppend(&sys->pp_packets_next, block);
if(end)
{
block_t *out = block_ChainGather(sys->p_packets);
sys->p_packets = NULL;
sys->pp_packets_next = &sys->p_packets;
out = h26x_wrap_prefix(out, true);
h26x_output(sys, out, pts, true, b_au_end);
}
break;
}
case 50: /* PACI */
{
if(block->i_buffer < 5 || (block->p_buffer[3] & 0x01))
goto drop;
const uint8_t cType = ((block->p_buffer[2] & 0x7f) >> 1);
const uint8_t PHSize = ((block->p_buffer[2] & 0x01) << 7)
| (block->p_buffer[3] >> 4);
if(PHSize >= block->i_buffer - 4)
goto drop;
/* skip extension, and add the payload header */
block->p_buffer[0] = (block->p_buffer[0] & 0x81) | (cType << 1);
block->p_buffer[4 + PHSize - 2 + 0] = block->p_buffer[0];
block->p_buffer[4 + PHSize - 2 + 1] = block->p_buffer[1];
block->p_buffer -= 4 + PHSize;
block->i_buffer += 4 + PHSize;
/* pass to original payload handler */
rtp_h265_decode(pt, data, block, info);
break;
}
default:
/* end unfinished aggregates */
h26x_output_blocks(sys, true);
/* raw single NAL */
if(sys->flags & FLAG_DONL) /* optional DONL */
{
if(block->i_buffer < 4)
goto drop;
/* NALHDR DONL NALPAYL -> NALHDR NALPAYL */
block->p_buffer[2] = block->p_buffer[0];
block->p_buffer[3] = block->p_buffer[1];
block->p_buffer += 2;
block->i_buffer -= 2;
}
block = h26x_wrap_prefix(block, true);
h26x_output(sys, block, pts, true, b_au_end);
}
return;
drop:
if(block)
block_Release(block);
}
static void rtp_h265_release(struct vlc_rtp_pt *pt)
{
struct h265_pt_opaque *opaque = pt->opaque;
if(opaque->sdpxps)
block_Release(opaque->sdpxps);
free(opaque);
}
static const struct vlc_rtp_pt_operations rtp_h265_ops = {
rtp_h265_release, rtp_h265_init, rtp_h265_destroy, rtp_h265_decode,
};
static int rtp_h265_open(vlc_object_t *obj, struct vlc_rtp_pt *pt,
const struct vlc_sdp_pt *desc)
{
if (vlc_ascii_strcasecmp(desc->name, "H265") == 0)
pt->ops = &rtp_h265_ops;
else
return VLC_ENOTSUP;
struct h265_pt_opaque *opaque = calloc(1, sizeof(*opaque));
if(!opaque)
return VLC_ENOMEM;
pt->opaque = opaque;
opaque->obj = obj;
if(desc->parameters)
{
const char *psz = strstr(desc->parameters, "sprop-max-don-diff=");
if(psz)
opaque->b_donl = (atoi(psz + 19) > 0);
block_t **append = &opaque->sdpxps;
const char *props[] = { "sprop-vps=", "sprop-sps=", "sprop-pps=" };
for(int i=0; i<ARRAY_SIZE(props); i++)
{
psz = strstr(desc->parameters, props[i]);
if(!psz)
continue;
block_t *xps = h26x_fillextradata(psz + 10);
if(xps)
block_ChainLastAppend(&append, xps);
}
if(opaque->sdpxps)
opaque->sdpxps = block_ChainGather(opaque->sdpxps);
}
return VLC_SUCCESS;
}
vlc_module_begin()
set_shortname(N_("RTP H265"))
set_description(N_("RTP H265 payload parser"))
set_subcategory(SUBCAT_INPUT_DEMUX)
set_rtp_parser_callback(rtp_h265_open)
add_shortcut("video/H265")
vlc_module_end()
/**
* @file h26x.h
*/
/*****************************************************************************
* Copyright (C) 2022 VideoLabs, VLC authors and VideoLAN
*
* This library 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.
*
* This library 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
#include <vlc_common.h>
#include <vlc_block.h>
#include <vlc_strings.h>
#include <vlc_codec.h>
#include <vlc_demux.h>
#include "rtp.h"
#include "../live555_dtsgen.h"
static const uint8_t annexbheader[] = { 0, 0, 0, 1 };
struct rtp_h26x_sys
{
unsigned flags;
vlc_tick_t pts;
block_t **pp_packets_next;
block_t *p_packets;
block_t *xps;
struct vlc_rtp_es *es;
decoder_t *p_packetizer;
struct dtsgen_t dtsgen;
};
static void rtp_h26x_clear(struct rtp_h26x_sys *sys)
{
block_ChainRelease(sys->p_packets);
if(sys->xps)
block_Release(sys->xps);
}
static void rtp_h26x_init(struct rtp_h26x_sys *sys)
{
sys->flags = 0;
sys->pts = VLC_TICK_INVALID;
sys->p_packets = NULL;
sys->pp_packets_next = &sys->p_packets;
sys->xps = NULL;
sys->es = NULL;
sys->p_packetizer = NULL;
dtsgen_Init(&sys->dtsgen);
}
static void h26x_extractbase64xps(const char *psz64,
const char *pszend,
void(*pf_output)(void *, uint8_t *, size_t),
void *outputsys)
{
do
{
psz64 += strspn(psz64, " ");
uint8_t *xps = NULL;
size_t xpssz = vlc_b64_decode_binary(&xps, psz64);
pf_output(outputsys, xps, xpssz);
psz64 = strchr(psz64, ',');
if(psz64)
++psz64;
} while(psz64 && *psz64 && psz64 < pszend);
}
static block_t * h26x_wrap_prefix(block_t *block, bool b_annexb)
{
block = block_Realloc(block, 4, block->i_buffer);
if(block)
{
if(b_annexb)
memcpy(block->p_buffer, annexbheader, 4);
else
SetDWBE(block->p_buffer, block->i_buffer - 4);
}
return block;
}
static void h26x_add_xps(void *priv, uint8_t *xps, size_t xpssz)
{
block_t *b = block_heap_Alloc(xps, xpssz);
if(!b || !(b = h26x_wrap_prefix(b, true)))
return;
block_t ***ppp_append = priv;
**ppp_append = b;
*ppp_append = &((**ppp_append)->p_next);
}
static block_t * h26x_fillextradata (const char *psz)
{
block_t *xps = NULL;
block_t **pxps = &xps;
h26x_extractbase64xps(psz, strchr(psz, ';'), h26x_add_xps, &pxps);
if(xps)
xps = block_ChainGather(xps);
return xps;
}
static void h26x_output(struct rtp_h26x_sys *sys,
block_t *block,
vlc_tick_t pts, bool pcr, bool au_end)
{
if(!block)
return;
if(sys->xps)
{
block_t *xps = sys->xps;
sys->xps = NULL;
h26x_output(sys, xps, pts, pcr, false);
}
if(block->i_flags & BLOCK_FLAG_DISCONTINUITY)
dtsgen_Resync(&sys->dtsgen);
block->i_pts = pts;
block->i_dts = VLC_TICK_INVALID; /* RTP does not specify this */
if(au_end)
block->i_flags |= BLOCK_FLAG_AU_END;
block_t *p_out;
for(int i=0; i<(1+!!au_end); i++)
{
while((p_out = sys->p_packetizer->pf_packetize(sys->p_packetizer,
block ? &block : NULL)))
{
dtsgen_AddNextPTS(&sys->dtsgen, p_out->i_pts);
vlc_tick_t dts = dtsgen_GetDTS(&sys->dtsgen);
p_out->i_dts = dts;
vlc_rtp_es_send(sys->es, p_out);
}
block = NULL; // for drain iteration
}
}
static void h26x_output_blocks(struct rtp_h26x_sys *sys, bool b_annexb)
{
if(!sys->p_packets)
return;
block_t *out = block_ChainGather(sys->p_packets);
sys->p_packets = NULL;
sys->pp_packets_next = &sys->p_packets;
out = h26x_wrap_prefix(out, b_annexb);
h26x_output(sys, out, sys->pts, true, false);
}
......@@ -78,8 +78,10 @@ static void vlc_rtp_es_id_send(struct vlc_rtp_es *es, block_t *block)
/* TODO: Don't set PCR here. Breaks multiple sources (in a session)
* and more importantly eventually multiple sessions. */
if (block->i_pts != VLC_TICK_INVALID)
es_out_SetPCR(ei->out, block->i_pts);
vlc_tick_t pcr = (block->i_dts != VLC_TICK_INVALID) ? block->i_dts
: block->i_pts;
if (pcr != VLC_TICK_INVALID)
es_out_SetPCR(ei->out, pcr);
es_out_Send(ei->out, ei->id, block);
}
......
......@@ -480,10 +480,6 @@ static int Demux( demux_t *p_demux)
bool frame = p_block_out->i_flags & BLOCK_FLAG_TYPE_MASK;
const vlc_tick_t i_frame_length = p_block_out->i_length;
/* first output */
if( date_Get( &p_sys->output_dts ) == VLC_TICK_0 )
es_out_SetPCR( p_demux->out, date_Get( &p_sys->output_dts ) );
es_out_Send( p_demux->out, p_sys->p_es, p_block_out );
vlc_tick_t pcr = b_eof ? dts : date_Get( &p_sys->output_dts );
......@@ -503,8 +499,6 @@ static int Demux( demux_t *p_demux)
}
}
es_out_SetPCR( p_demux->out, pcr );
p_block_out = p_next;
}
}
......