<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">On 08/22/2013 06:21 PM, Nisar Ahmed
wrote:<br>
</div>
<blockquote
cite="mid:CAL1+ejjbJ4pdN49JhupHer+PgvxPvJG+zZsSuFsPPecxr7DaDQ@mail.gmail.com"
type="cite">
<div dir="ltr">Coming back to this issue, I have tested 2
scenarios
<div><br>
</div>
<div>a. I am simply setting pts to the timestamp received from
encoder and dts to 0 but the resulting file is showing very
large frame rate value.</div>
<div><br>
</div>
<div>b. Setting pts to the timestamp received from encoder but
this time setting dts with an increment of 1001 starting from
-1001 (2002/-1001, 0/0, 1001/1001, 5005/2002, 3003/3003). The
framerate is correct this time but the quicktime player
displays a white frame at the start of the movie. I
investigated this issue further by using libav demuxer sample
and the pts/dts have been changed from what I set and
start_time is also not 0. VLC plays fine but I also want
Quicktime player to play the file normally as well.<br>
</div>
<div><br>
</div>
<div>The movies created by the software which ships with he
encoder shows correct frame rate and start time of 0, also the
pts/dts investigated with the demuxing sample are in the same
sequence as described in the second scenario.</div>
<div><br>
</div>
<div>I really need to understand why my pts/dts are changed by
the muxer to different values, may be it is trying to guess
correct values based on the inputs I provided. Which inputs
matter in this kind of scenarios and how they relate to each
other?</div>
<div><br>
</div>
<div>Thanks in advance</div>
<div>Nisar</div>
</div>
<div class="gmail_extra"><br>
<br>
<div class="gmail_quote">On Sat, Aug 17, 2013 at 11:05 AM, Nisar
Ahmed <span dir="ltr"><<a moz-do-not-send="true"
href="mailto:nisar.med@gmail.com" target="_blank">nisar.med@gmail.com</a>></span>
wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0
.8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr">Thanks for your answer, when I set timestamp
of decoder, the frame rate jumps up to a very large value
<div>
<br>
</div>
<div><span
style="font-family:arial,sans-serif;font-size:13px">pts/dts
= (2002/0, 0/0, 1001/0, 5005/0, 3003/0...)</span><br>
</div>
<div><span
style="font-family:arial,sans-serif;font-size:13px"><br>
</span></div>
<div><span
style="font-family:arial,sans-serif;font-size:13px">am
I setting the time_base to correct values 1001/30000
and pkt.duration = 1001? the timescale of the
timestamp is also 30000</span></div>
</div>
<div class="HOEnZb">
<div class="h5">
<div class="gmail_extra"><br>
<br>
<div class="gmail_quote">On Sat, Aug 17, 2013 at 2:10
AM, Anshul maheshwari <span dir="ltr"><<a
moz-do-not-send="true"
href="mailto:er.anshul.maheshwari@gmail.com"
target="_blank">er.anshul.maheshwari@gmail.com</a>></span>
wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0
.8ex;border-left:1px #ccc solid;padding-left:1ex">
<p>-</p>
<div>
<div><br>
On Aug 16, 2013 7:30 PM, "Nisar Ahmed" <<a
moz-do-not-send="true"
href="mailto:nisar.med@gmail.com"
target="_blank">nisar.med@gmail.com</a>>
wrote:<br>
><br>
> I am muxing h264/aac stream to mp4 coming
from an encoder and having issues syncing
audio and video streams.<br>
><br>
> I suspect that the problem is with PTS
and DTS but I am not sure what values should i
set to properly sync both streams.<br>
><br>
> I have set the time_base of video
stream's AVCodecContext to 1001/30000 and each
AVPacket gets a duration of 1001<br>
><br>
> I am recieving time stamps from the
encoder with each NAL packet which is set as
PTS of the AVPacket. the sequence of PTS/DTS I
set is (2002/0, 0/1001, 1001/2002, 5005/3003,
3003/4004...)<br>
><br>
> Audio stream AVCodecContext sample rate
is 48000 and PTS/DTS are simply multiples of
1024 starting from 0 and AVPacket duration is
1024.<br>
><br>
> The output movie 's frame rate is 20fps
when it should be 29.97fps as it is ntsc.<br>
><br>
> Please tell me how to debug this problem
and what are the guidelines of creating
pts/dts for both video and audio in my case<br>
><br>
</div>
</div>
>
_______________________________________________<br>
> Libav-user mailing list<br>
> <a moz-do-not-send="true"
href="mailto:Libav-user@ffmpeg.org"
target="_blank">Libav-user@ffmpeg.org</a><br>
> <a moz-do-not-send="true"
href="http://ffmpeg.org/mailman/listinfo/libav-user"
target="_blank">http://ffmpeg.org/mailman/listinfo/libav-user</a><br>
><br>
Hi naseer
<p>If you are getting timestamp with encoder, i
would suggest "dont try to manuplate that" you
may set that same timestamp as presentation
timestamp (pts) if your video is realtime then
try not to generate B type video frame hence no
need to set dts.<br>
Whatever clock is set by encoder try generating
the pts of audio according to that.</p>
<p>@enjoy<span><font color="#888888"><br>
Anshul</font></span></p>
<br>
_______________________________________________<br>
Libav-user mailing list<br>
<a moz-do-not-send="true"
href="mailto:Libav-user@ffmpeg.org"
target="_blank">Libav-user@ffmpeg.org</a><br>
<a moz-do-not-send="true"
href="http://ffmpeg.org/mailman/listinfo/libav-user"
target="_blank">http://ffmpeg.org/mailman/listinfo/libav-user</a><br>
<br>
</blockquote>
</div>
<br>
</div>
</div>
</div>
</blockquote>
</div>
<br>
</div>
<br>
<fieldset class="mimeAttachmentHeader"></fieldset>
<br>
<pre wrap="">_______________________________________________
Libav-user mailing list
<a class="moz-txt-link-abbreviated" href="mailto:Libav-user@ffmpeg.org">Libav-user@ffmpeg.org</a>
<a class="moz-txt-link-freetext" href="http://ffmpeg.org/mailman/listinfo/libav-user">http://ffmpeg.org/mailman/listinfo/libav-user</a>
</pre>
</blockquote>
please don't top post over here,<br>
<br>
>I really need to understand why my pts/dts are changed by the
muxer to different values, may be it is trying to guess correct
values based on the inputs I provided. Which <br>
>inputs matter in this kind of scenarios and how they relate to
each other?<br>
<br>
Muxer does not change the pts or dts if you have provided by your
own, may be you are unable to set pts, dts in your muxer.<br>
please refer below code, it is not kind of tutorial but extract
needed part.<br>
<br>
Note: your a part wont work because your h264 elementary stream
contain b frame, where dts is important part.<br>
and your b part wont work, there might be simple reason
for that it does not calculate start time properly, so when it is 0
as with your software <br>
then it work.<br>
<br>
Below is very badly written code, but its work :)<br>
<br>
#include <stdlib.h><br>
#include <stdio.h><br>
#include <string.h><br>
#include <math.h><br>
#include <libavutil/mathematics.h><br>
#include <libavformat/avformat.h><br>
#include <libxml/tree.h><br>
#define MAX_STREAM 2<br>
#define BUFF_SIZE ( 1920 *1080 )<br>
#define STREAM_DURATION ( 200.0 )<br>
#define STREAM_FRAME_RATE ( 25 )<br>
#define AUDIO_BITRATE ( 64000 )<br>
#define AUDIO_CHANNEL ( 2 )<br>
#define FRAME_SIZE ( 1024 )<br>
#define VIDEO_BITRATE ( 400000 )<br>
#define VIDEO_WIDTH ( 1920 )<br>
#define VIDEO_HEIGHT ( 1080 )<br>
#define VIDEO_GOP ( 12 )<br>
#define OUTPUT_CONTEXT_FORMAT "mpegts"<br>
#define HLS_NUM_CALLBACKS 2<br>
<br>
typedef int (*callbackFn)(void *);<br>
<br>
struct mux_cfg<br>
{<br>
int no_of_stream;<br>
enum AVCodecID codec_id[MAX_STREAM];<br>
int audio_sample_rate;<br>
int video_frame_rate;<br>
<br>
AVStream *st[MAX_STREAM];<br>
AVFormatContext *oc;<br>
unsigned char *obuffer;<br>
<br>
//user specific buffer<br>
unsigned char uobuffer[BUFF_SIZE];<br>
int uosize;<br>
int64_t uopts;<br>
<br>
int pts_generator;<br>
<br>
};<br>
<br>
enum MediaType {<br>
VIDEO,<br>
AUDIO<br>
};<br>
<br>
struct mediaBuffer{<br>
int size;<br>
unsigned char *data ;<br>
enum MediaType mtype;<br>
int64_t pts;<br>
int64_t dts;<br>
};<br>
<br>
int init(char *xml);<br>
int start(void);<br>
int get_buffer(void *pOutputData);<br>
int put_buffer(void *pInputData);<br>
int stop(void);<br>
int deinit(void);<br>
<br>
struct mux_cfg glb_cfg;<br>
<br>
static int mux_write(void* opaque, char*buf, int size);<br>
static int parse_xml(char*xml,struct mux_cfg *cfg);<br>
static int update_input_param(xmlNodePtr ParentNode, struct mux_cfg
*cfg,xmlDocPtr doc);<br>
<br>
static int Muxer_init(struct mux_cfg *loc_cfg, char *xml);<br>
static int Muxer_get_buffer(struct mux_cfg *loc_cfg,void
*pOutputData);<br>
static int Muxer_put_buffer(struct mux_cfg *loc_cfg,void
*pInputData);<br>
static int Muxer_dinit(struct mux_cfg *loc_cfg);<br>
<br>
<br>
int init(char *xml)<br>
{<br>
return Muxer_init(&glb_cfg,xml);<br>
}<br>
<br>
int start(void)<br>
{<br>
return 0;<br>
}<br>
<br>
int getCallbackFns(int no, callbackFn* ptr)<br>
{<br>
<br>
int retValue = -1;<br>
<br>
if (no != HLS_NUM_CALLBACKS)<br>
{<br>
printf("Error: Invalid input callback number: %d\n", no);<br>
return retValue;<br>
}<br>
<br>
if (ptr)<br>
{<br>
ptr[0] = put_buffer;<br>
ptr[1] = get_buffer;<br>
retValue = 0;<br>
}<br>
else<br>
{<br>
printf("Error: Invalid pointer passed for callback!\n");<br>
return retValue;<br>
<br>
}<br>
<br>
return retValue;<br>
}<br>
<br>
int get_buffer(void *pOutputData)<br>
{<br>
return Muxer_get_buffer(&glb_cfg,pOutputData);<br>
}<br>
<br>
int put_buffer(void *pInputData)<br>
{<br>
return Muxer_put_buffer(&glb_cfg,pInputData);<br>
}<br>
<br>
int stop(void)<br>
{<br>
return 0;<br>
}<br>
<br>
int deinit(void)<br>
{<br>
return Muxer_dinit(&glb_cfg);<br>
}<br>
<br>
static AVStream *add_stream(AVFormatContext *oc, AVCodec **codec,<br>
struct mux_cfg *loc_cfg)<br>
{<br>
AVCodecContext *c;<br>
AVStream *st;<br>
<br>
st = avformat_new_stream(oc, *codec);<br>
if (!st)<br>
{<br>
fprintf(stderr, "Could not allocate stream\n");<br>
exit(1);<br>
}<br>
st->id = oc->nb_streams - 1;<br>
c = st->codec;<br>
<br>
switch ((*codec)->type)<br>
{<br>
case AVMEDIA_TYPE_AUDIO:<br>
c->codec_id = loc_cfg->codec_id[AUDIO];<br>
c->sample_fmt = AV_SAMPLE_FMT_S16;<br>
c->bit_rate = AUDIO_BITRATE;<br>
c->sample_rate = loc_cfg->audio_sample_rate;<br>
c->channels = AUDIO_CHANNEL;<br>
c->frame_size = FRAME_SIZE;<br>
<br>
break;<br>
<br>
case AVMEDIA_TYPE_VIDEO:<br>
c->codec_id = loc_cfg->codec_id[VIDEO];<br>
<br>
c->bit_rate = VIDEO_BITRATE;<br>
c->width = VIDEO_WIDTH;<br>
c->height = VIDEO_HEIGHT;<br>
c->time_base.den = loc_cfg->video_frame_rate;<br>
c->time_base.num = 1;<br>
c->gop_size = VIDEO_GOP; /* emit one intra frame
every twelve frames at most */<br>
c->pix_fmt = AV_PIX_FMT_YUV420P;<br>
break;<br>
<br>
default:<br>
break;<br>
}<br>
<br>
return st;<br>
}<br>
<br>
static int Muxer_init(struct mux_cfg *loc_cfg, char *xml)<br>
{<br>
int i = 0;<br>
int ret = 0;<br>
AVCodec *codec[MAX_STREAM];<br>
<br>
memset(loc_cfg, 0, sizeof(*loc_cfg));<br>
/* Initialize libavcodec, and register all codecs and formats.
*/<br>
av_register_all();<br>
<br>
parse_xml(xml,loc_cfg);<br>
<br>
/* allocate the output media context */<br>
avformat_alloc_output_context2(&loc_cfg->oc,
NULL,OUTPUT_CONTEXT_FORMAT, NULL );<br>
if (!loc_cfg->oc)<br>
{<br>
fprintf(stderr,"unable to allocate allocate context\n");<br>
}<br>
<br>
loc_cfg->obuffer = malloc(BUFF_SIZE);<br>
<br>
loc_cfg->oc->pb = avio_alloc_context(loc_cfg->obuffer,
BUFF_SIZE, AVIO_FLAG_WRITE,<br>
(void*) loc_cfg,NULL, (void*)
mux_write, NULL );<br>
for (i = 0; i < loc_cfg->no_of_stream; i++)<br>
{<br>
codec[i] = avcodec_find_encoder(loc_cfg->codec_id[i]);<br>
if (!(codec[i]))<br>
{<br>
fprintf(stderr, "Could not find encoder for '%s'\n",<br>
avcodec_get_name(loc_cfg->codec_id[i]));<br>
return -1;<br>
}<br>
<br>
loc_cfg->st[i] = add_stream(loc_cfg->oc,
&codec[i], loc_cfg);<br>
}<br>
<br>
ret = avformat_write_header(loc_cfg->oc, NULL );<br>
if (ret < 0)<br>
{<br>
fprintf(stderr, "Error occurred when opening output file:
%s\n",<br>
av_err2str(ret));<br>
return 1;<br>
}<br>
<br>
return 0;<br>
}<br>
<br>
static int Muxer_get_buffer(struct mux_cfg *loc_cfg,void
*pOutputData)<br>
{<br>
<br>
struct mediaBuffer *buf = (void*) pOutputData;<br>
<br>
if(!loc_cfg)<br>
{<br>
errno = EINVAL;<br>
return -1;<br>
}<br>
<br>
if(loc_cfg->pts_generator)<br>
{<br>
buf->pts = loc_cfg->uopts;<br>
buf->dts = 0;<br>
<br>
}<br>
else<br>
{<br>
buf->pts = 0;<br>
buf->dts = 0;<br>
}<br>
<br>
if (loc_cfg->uosize == 0)<br>
{<br>
return 0;<br>
}<br>
<br>
buf->data = loc_cfg->uobuffer;<br>
buf->size = loc_cfg->uosize;<br>
<br>
loc_cfg->uosize = 0;<br>
<br>
return buf->size;<br>
}<br>
static int Muxer_put_buffer(struct mux_cfg *loc_cfg,void
*pInputData)<br>
{<br>
struct mediaBuffer *buf = (void*) pInputData;<br>
int ret;<br>
AVPacket pkt;<br>
<br>
av_init_packet(&pkt);<br>
<br>
if(!loc_cfg)<br>
return -1;<br>
<br>
if(!loc_cfg->pts_generator)<br>
{<br>
pkt.pts = buf->pts;<br>
pkt.dts = buf->dts;<br>
}<br>
else<br>
{<br>
// pkt.pts = 0;<br>
// pkt.dts = 0;<br>
}<br>
pkt.data = buf->data;<br>
pkt.size = buf->size;<br>
<br>
pkt.stream_index = buf->mtype;<br>
<br>
ret = av_interleaved_write_frame(loc_cfg->oc, &pkt);<br>
if (ret < 0)<br>
{<br>
fprintf(stderr, "av_interleaved_write_frame : %s\n",
av_err2str(ret));<br>
}<br>
loc_cfg->uopts = pkt.pts;<br>
return ret;<br>
}<br>
<br>
static int mux_write(void* opaque, char*buf, int size)<br>
{<br>
struct mux_cfg *loc_cfg = opaque;<br>
memcpy(loc_cfg->uobuffer + loc_cfg->uosize, buf, size);<br>
loc_cfg->uosize += size;<br>
return 0;<br>
<br>
}<br>
<br>
int Muxer_dinit(struct mux_cfg *loc_cfg)<br>
{<br>
int i = 0;<br>
av_write_trailer(loc_cfg->oc);<br>
<br>
<br>
for(i = 0;i< loc_cfg->no_of_stream ;i++)<br>
{<br>
avcodec_close(loc_cfg->st[i]->codec);<br>
}<br>
av_free(loc_cfg->oc->pb);<br>
/* free the stream */<br>
avformat_free_context(loc_cfg->oc);<br>
<br>
return 0;<br>
<br>
}<br>
<br>
<br>
static int parse_xml(char*xml,struct mux_cfg *cfg)<br>
{<br>
int ret = 0;<br>
xmlDocPtr doc;<br>
xmlNodePtr nl1;<br>
<br>
if(!xml || !cfg)<br>
{<br>
ret= -1;<br>
return ret;<br>
}<br>
doc = xmlParseFile(xml);<br>
if (doc == NULL)<br>
{<br>
ret= -1;<br>
return ret;<br>
<br>
}<br>
for (nl1 = doc->children; nl1 != NULL; nl1 = nl1->next)<br>
{<br>
ret = xmlStrcmp(nl1->name, (const xmlChar *) "INPUT");<br>
if (ret == 0)<br>
{<br>
update_input_param(nl1,cfg,doc);<br>
}<br>
}<br>
<br>
xmlFreeDoc(doc);<br>
return ret;<br>
}<br>
static int update_input_param(xmlNodePtr ParentNode, struct mux_cfg
*cfg,xmlDocPtr doc)<br>
{<br>
<br>
xmlNodePtr nl = ParentNode->children;<br>
char *pXmlGetString = NULL;<br>
<br>
int ret = 0;<br>
for (; nl != NULL; nl = nl->next)<br>
{<br>
ret = xmlStrcmp(nl->name, (const xmlChar *)
"no_of_elem_stream");<br>
if (ret == 0)<br>
{<br>
pXmlGetString = (char *) xmlNodeListGetString(doc,<br>
nl->xmlChildrenNode, 1);<br>
sscanf(pXmlGetString, "%d", &cfg->no_of_stream);<br>
xmlFree(pXmlGetString);<br>
<br>
}<br>
<br>
ret = xmlStrcmp(nl->name, (const xmlChar *)
"audio_codec");<br>
if (ret == 0)<br>
{<br>
pXmlGetString = (char *) xmlNodeListGetString(doc,<br>
nl->xmlChildrenNode, 1);<br>
if(!strcmp(pXmlGetString,"aac"))<br>
{<br>
cfg->codec_id[AUDIO] = AV_CODEC_ID_AAC;<br>
}<br>
xmlFree(pXmlGetString);<br>
}<br>
<br>
ret = xmlStrcmp(nl->name, (const xmlChar *)
"video_codec");<br>
if (ret == 0)<br>
{<br>
pXmlGetString = (char *) xmlNodeListGetString(doc,<br>
nl->xmlChildrenNode, 1);<br>
if(!strcmp(pXmlGetString,"h264"))<br>
{<br>
cfg->codec_id[VIDEO] = AV_CODEC_ID_H264;<br>
}<br>
xmlFree(pXmlGetString);<br>
<br>
}<br>
<br>
ret = xmlStrcmp(nl->name, (const xmlChar *)
"audio_sample_rate");<br>
if (ret == 0)<br>
{<br>
pXmlGetString = (char *) xmlNodeListGetString(doc,<br>
nl->xmlChildrenNode, 1);<br>
sscanf(pXmlGetString, "%d",
&cfg->audio_sample_rate);<br>
xmlFree(pXmlGetString);<br>
<br>
}<br>
<br>
ret = xmlStrcmp(nl->name, (const xmlChar *)
"video_frame_rate");<br>
if (ret == 0)<br>
{<br>
pXmlGetString = (char *) xmlNodeListGetString(doc,<br>
nl->xmlChildrenNode, 1);<br>
sscanf(pXmlGetString, "%d",
&cfg->video_frame_rate);<br>
xmlFree(pXmlGetString);<br>
<br>
}<br>
<br>
ret = xmlStrcmp(nl->name, (const xmlChar *)
"pts_generator");<br>
if (ret == 0)<br>
{<br>
pXmlGetString = (char *) xmlNodeListGetString(doc,<br>
nl->xmlChildrenNode, 1);<br>
if(!strcmp(pXmlGetString,"TRUE") ||
!strcmp(pXmlGetString,"true"))<br>
{<br>
cfg->pts_generator = 1;<br>
}<br>
xmlFree(pXmlGetString);<br>
<br>
}<br>
<br>
<br>
}<br>
return ret;<br>
}<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
</body>
</html>