AVCodecParserContext *s;
AVCodecParser *parser;
int ret;
+
+ if(codec_id == CODEC_ID_NONE)
+ return NULL;
for(parser = av_first_parser; parser != NULL; parser = parser->next) {
if (parser->codec_ids[0] == codec_id ||
parser->codec_ids[1] == codec_id ||
- parser->codec_ids[2] == codec_id)
+ parser->codec_ids[2] == codec_id ||
+ parser->codec_ids[3] == codec_id ||
+ parser->codec_ids[4] == codec_id)
goto found;
}
return NULL;
return NULL;
}
}
+ s->fetch_timestamp=1;
return s;
}
+/* NOTE: buf_size == 0 is used to signal EOF so that the last frame
+ can be returned if necessary */
int av_parser_parse(AVCodecParserContext *s,
AVCodecContext *avctx,
uint8_t **poutbuf, int *poutbuf_size,
- const uint8_t *buf, int buf_size)
+ const uint8_t *buf, int buf_size,
+ int64_t pts, int64_t dts)
{
- int index;
+ int index, i, k;
+ uint8_t dummy_buf[FF_INPUT_BUFFER_PADDING_SIZE];
+
+ if (buf_size == 0) {
+ /* padding is always necessary even if EOF, so we add it here */
+ memset(dummy_buf, 0, sizeof(dummy_buf));
+ buf = dummy_buf;
+ } else {
+ /* add a new packet descriptor */
+ k = (s->cur_frame_start_index + 1) & (AV_PARSER_PTS_NB - 1);
+ s->cur_frame_start_index = k;
+ s->cur_frame_offset[k] = s->cur_offset;
+ s->cur_frame_pts[k] = pts;
+ s->cur_frame_dts[k] = dts;
+
+ /* fill first PTS/DTS */
+ if (s->fetch_timestamp){
+ s->fetch_timestamp=0;
+ s->last_pts = pts;
+ s->last_dts = dts;
+ s->cur_frame_pts[k] =
+ s->cur_frame_dts[k] = AV_NOPTS_VALUE;
+ }
+ }
+
/* WARNING: the returned index can be negative */
index = s->parser->parser_parse(s, avctx, poutbuf, poutbuf_size, buf, buf_size);
+//av_log(NULL, AV_LOG_DEBUG, "parser: in:%lld, %lld, out:%lld, %lld, in:%d out:%d id:%d\n", pts, dts, s->last_pts, s->last_dts, buf_size, *poutbuf_size, avctx->codec_id);
/* update the file pointer */
if (*poutbuf_size) {
+ /* fill the data for the current frame */
s->frame_offset = s->last_frame_offset;
+ s->pts = s->last_pts;
+ s->dts = s->last_dts;
+
+ /* offset of the next frame */
s->last_frame_offset = s->cur_offset + index;
+ /* find the packet in which the new frame starts. It
+ is tricky because of MPEG video start codes
+ which can begin in one packet and finish in
+ another packet. In the worst case, an MPEG
+ video start code could be in 4 different
+ packets. */
+ k = s->cur_frame_start_index;
+ for(i = 0; i < AV_PARSER_PTS_NB; i++) {
+ if (s->last_frame_offset >= s->cur_frame_offset[k])
+ break;
+ k = (k - 1) & (AV_PARSER_PTS_NB - 1);
+ }
+
+ s->last_pts = s->cur_frame_pts[k];
+ s->last_dts = s->cur_frame_dts[k];
+
+ /* some parsers tell us the packet size even before seeing the first byte of the next packet,
+ so the next pts/dts is in the next chunk */
+ if(index == buf_size){
+ s->fetch_timestamp=1;
+ }
}
if (index < 0)
index = 0;
return index;
}
+/**
+ *
+ * @return 0 if the output buffer is a subset of the input, 1 if it is allocated and must be freed
+ */
+int av_parser_change(AVCodecParserContext *s,
+ AVCodecContext *avctx,
+ uint8_t **poutbuf, int *poutbuf_size,
+ const uint8_t *buf, int buf_size, int keyframe){
+
+ if(s && s->parser->split){
+ if((avctx->flags & CODEC_FLAG_GLOBAL_HEADER) || (avctx->flags2 & CODEC_FLAG2_LOCAL_HEADER)){
+ int i= s->parser->split(avctx, buf, buf_size);
+ buf += i;
+ buf_size -= i;
+ }
+ }
+
+ *poutbuf= buf;
+ *poutbuf_size= buf_size;
+ if(avctx->extradata){
+ if( (keyframe && (avctx->flags2 & CODEC_FLAG2_LOCAL_HEADER))
+ /*||(s->pict_type != I_TYPE && (s->flags & PARSER_FLAG_DUMP_EXTRADATA_AT_NOKEY))*/
+ /*||(? && (s->flags & PARSER_FLAG_DUMP_EXTRADATA_AT_BEGIN)*/){
+ int size= buf_size + avctx->extradata_size;
+ *poutbuf_size= size;
+ *poutbuf= av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
+
+ memcpy(*poutbuf, avctx->extradata, avctx->extradata_size);
+ memcpy((*poutbuf) + avctx->extradata_size, buf, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
void av_parser_close(AVCodecParserContext *s)
{
if (s->parser->parser_close)
#define SLICE_MAX_START_CODE 0x000001af
typedef struct ParseContext1{
- uint8_t *buffer;
- int index;
- int last_index;
- int buffer_size;
- uint32_t state; ///< contains the last few bytes in MSB order
- int frame_start_found;
- int overread; ///< the number of bytes which where irreversibly read from the next frame
- int overread_index; ///< the index into ParseContext1.buffer of the overreaded bytes
-
+ ParseContext pc;
+/* XXX/FIXME PC1 vs. PC */
/* MPEG2 specific */
int frame_rate;
int progressive_sequence;
int width, height;
+
/* XXX: suppress that, needed by MPEG4 */
MpegEncContext *enc;
+ int first_picture;
} ParseContext1;
/**
* combines the (truncated) bitstream to a complete frame
* @returns -1 if no complete frame could be created
*/
-static int ff_combine_frame1(ParseContext1 *pc, int next, uint8_t **buf, int *buf_size)
+int ff_combine_frame(ParseContext *pc, int next, uint8_t **buf, int *buf_size)
{
#if 0
if(pc->overread){
for(; pc->overread>0; pc->overread--){
pc->buffer[pc->index++]= pc->buffer[pc->overread_index++];
}
-
+
+ /* flush remaining if EOF */
+ if(!*buf_size && next == END_NOT_FOUND){
+ next= 0;
+ }
+
pc->last_index= pc->index;
/* copy into buffer end return */
return 0;
}
-/**
- * finds the end of the current frame in the bitstream.
- * @return the position of the first byte of the next frame, or -1
- */
-static int mpeg1_find_frame_end(ParseContext1 *pc, const uint8_t *buf, int buf_size)
-{
- int i;
- uint32_t state;
-
- state= pc->state;
-
- i=0;
- if(!pc->frame_start_found){
- for(i=0; i<buf_size; i++){
- state= (state<<8) | buf[i];
- if(state >= SLICE_MIN_START_CODE && state <= SLICE_MAX_START_CODE){
- i++;
- pc->frame_start_found=1;
- break;
- }
- }
- }
-
- if(pc->frame_start_found){
- for(; i<buf_size; i++){
- state= (state<<8) | buf[i];
- if((state&0xFFFFFF00) == 0x100){
- if(state < SLICE_MIN_START_CODE || state > SLICE_MAX_START_CODE){
- pc->frame_start_found=0;
- pc->state=-1;
- return i-3;
- }
- }
- }
- }
- pc->state= state;
- return END_NOT_FOUND;
-}
-
static int find_start_code(const uint8_t **pbuf_ptr, const uint8_t *buf_end)
{
const uint8_t *buf_ptr;
25025,
};
+//FIXME move into mpeg12.c
static void mpegvideo_extract_headers(AVCodecParserContext *s,
AVCodecContext *avctx,
const uint8_t *buf, int buf_size)
int32_t start_code;
int frame_rate_index, ext_type, bytes_left;
int frame_rate_ext_n, frame_rate_ext_d;
- int top_field_first, repeat_first_field, progressive_frame;
- int horiz_size_ext, vert_size_ext;
-
+ int picture_structure, top_field_first, repeat_first_field, progressive_frame;
+ int horiz_size_ext, vert_size_ext, bit_rate_ext;
+//FIXME replace the crap with get_bits()
s->repeat_pict = 0;
buf_end = buf + buf_size;
while (buf < buf_end) {
}
break;
case SEQ_START_CODE:
- if (bytes_left >= 4) {
- pc->width = avctx->width = (buf[0] << 4) | (buf[1] >> 4);
- pc->height = avctx->height = ((buf[1] & 0x0f) << 8) | buf[2];
+ if (bytes_left >= 7) {
+ pc->width = (buf[0] << 4) | (buf[1] >> 4);
+ pc->height = ((buf[1] & 0x0f) << 8) | buf[2];
+ avcodec_set_dimensions(avctx, pc->width, pc->height);
frame_rate_index = buf[3] & 0xf;
- pc->frame_rate = avctx->frame_rate = frame_rate_tab[frame_rate_index];
- avctx->frame_rate_base = MPEG1_FRAME_RATE_BASE;
+ pc->frame_rate = avctx->time_base.den = frame_rate_tab[frame_rate_index];
+ avctx->time_base.num = MPEG1_FRAME_RATE_BASE;
+ avctx->bit_rate = ((buf[4]<<10) | (buf[5]<<2) | (buf[6]>>6))*400;
+ avctx->codec_id = CODEC_ID_MPEG1VIDEO;
+ avctx->sub_id = 1;
}
break;
case EXT_START_CODE:
if (bytes_left >= 6) {
horiz_size_ext = ((buf[1] & 1) << 1) | (buf[2] >> 7);
vert_size_ext = (buf[2] >> 5) & 3;
+ bit_rate_ext = ((buf[2] & 0x1F)<<7) | (buf[3]>>1);
frame_rate_ext_n = (buf[5] >> 5) & 3;
frame_rate_ext_d = (buf[5] & 0x1f);
pc->progressive_sequence = buf[1] & (1 << 3);
-
- avctx->width = pc->width | (horiz_size_ext << 12);
- avctx->height = pc->height | (vert_size_ext << 12);
- avctx->frame_rate = pc->frame_rate * (frame_rate_ext_n + 1);
- avctx->frame_rate_base = MPEG1_FRAME_RATE_BASE * (frame_rate_ext_d + 1);
+ avctx->has_b_frames= !(buf[5] >> 7);
+
+ pc->width |=(horiz_size_ext << 12);
+ pc->height |=( vert_size_ext << 12);
+ avctx->bit_rate += (bit_rate_ext << 18) * 400;
+ avcodec_set_dimensions(avctx, pc->width, pc->height);
+ avctx->time_base.den = pc->frame_rate * (frame_rate_ext_n + 1);
+ avctx->time_base.num = MPEG1_FRAME_RATE_BASE * (frame_rate_ext_d + 1);
+ avctx->codec_id = CODEC_ID_MPEG2VIDEO;
avctx->sub_id = 2; /* forces MPEG2 */
}
break;
case 0x8: /* picture coding extension */
if (bytes_left >= 5) {
+ picture_structure = buf[2]&3;
top_field_first = buf[3] & (1 << 7);
repeat_first_field = buf[3] & (1 << 1);
progressive_frame = buf[4] & (1 << 7);
s->repeat_pict = 1;
}
}
+
+ /* the packet only represents half a frame
+ XXX,FIXME maybe find a different solution */
+ if(picture_structure != 3)
+ s->repeat_pict = -1;
}
break;
}
uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size)
{
- ParseContext1 *pc = s->priv_data;
+ ParseContext1 *pc1 = s->priv_data;
+ ParseContext *pc= &pc1->pc;
int next;
- next= mpeg1_find_frame_end(pc, buf, buf_size);
+ next= ff_mpeg1_find_frame_end(pc, buf, buf_size);
- if (ff_combine_frame1(pc, next, (uint8_t **)&buf, &buf_size) < 0) {
+ if (ff_combine_frame(pc, next, (uint8_t **)&buf, &buf_size) < 0) {
*poutbuf = NULL;
*poutbuf_size = 0;
return buf_size;
mpegvideo_extract_headers(s, avctx, buf, buf_size);
#if 0
printf("pict_type=%d frame_rate=%0.3f repeat_pict=%d\n",
- s->pict_type, (double)avctx->frame_rate / avctx->frame_rate_base, s->repeat_pict);
+ s->pict_type, (double)avctx->time_base.den / avctx->time_base.num, s->repeat_pict);
#endif
*poutbuf = (uint8_t *)buf;
return next;
}
-static void mpegvideo_parse_close(AVCodecParserContext *s)
+static int mpegvideo_split(AVCodecContext *avctx,
+ const uint8_t *buf, int buf_size)
{
- ParseContext1 *pc = s->priv_data;
+ int i;
+ uint32_t state= -1;
+
+ for(i=0; i<buf_size; i++){
+ state= (state<<8) | buf[i];
+ if(state != 0x1B3 && state != 0x1B5 && state < 0x200 && state >= 0x100)
+ return i-3;
+ }
+ return 0;
+}
+
+void ff_parse_close(AVCodecParserContext *s)
+{
+ ParseContext *pc = s->priv_data;
av_free(pc->buffer);
- av_free(pc->enc);
}
-/*************************/
-
-/**
- * finds the end of the current frame in the bitstream.
- * @return the position of the first byte of the next frame, or -1
- */
-static int mpeg4_find_frame_end(ParseContext1 *pc,
- const uint8_t *buf, int buf_size)
+static void parse1_close(AVCodecParserContext *s)
{
- int vop_found, i;
- uint32_t state;
-
- vop_found= pc->frame_start_found;
- state= pc->state;
-
- i=0;
- if(!vop_found){
- for(i=0; i<buf_size; i++){
- state= (state<<8) | buf[i];
- if(state == 0x1B6){
- i++;
- vop_found=1;
- break;
- }
- }
- }
+ ParseContext1 *pc1 = s->priv_data;
- if(vop_found){
- for(; i<buf_size; i++){
- state= (state<<8) | buf[i];
- if((state&0xFFFFFF00) == 0x100){
- pc->frame_start_found=0;
- pc->state=-1;
- return i-3;
- }
- }
- }
- pc->frame_start_found= vop_found;
- pc->state= state;
- return END_NOT_FOUND;
+ av_free(pc1->pc.buffer);
+ av_free(pc1->enc);
}
+/*************************/
+
/* used by parser */
/* XXX: make it use less memory */
static int av_mpeg4_decode_header(AVCodecParserContext *s1,
int ret;
s->avctx = avctx;
+ s->current_picture_ptr = &s->current_picture;
+
+ if (avctx->extradata_size && pc->first_picture){
+ init_get_bits(gb, avctx->extradata, avctx->extradata_size*8);
+ ret = ff_mpeg4_decode_picture_header(s, gb);
+ }
+
init_get_bits(gb, buf, 8 * buf_size);
ret = ff_mpeg4_decode_picture_header(s, gb);
if (s->width) {
- avctx->width = s->width;
- avctx->height = s->height;
+ avcodec_set_dimensions(avctx, s->width, s->height);
}
+ pc->first_picture = 0;
return ret;
}
-int mpeg4video_parse_init(AVCodecParserContext *s)
+static int mpeg4video_parse_init(AVCodecParserContext *s)
{
ParseContext1 *pc = s->priv_data;
+
pc->enc = av_mallocz(sizeof(MpegEncContext));
if (!pc->enc)
return -1;
+ pc->first_picture = 1;
return 0;
}
uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size)
{
- ParseContext1 *pc = s->priv_data;
+ ParseContext *pc = s->priv_data;
int next;
- next= mpeg4_find_frame_end(pc, buf, buf_size);
+ next= ff_mpeg4_find_frame_end(pc, buf, buf_size);
- if (ff_combine_frame1(pc, next, (uint8_t **)&buf, &buf_size) < 0) {
+ if (ff_combine_frame(pc, next, (uint8_t **)&buf, &buf_size) < 0) {
*poutbuf = NULL;
*poutbuf_size = 0;
return buf_size;
return next;
}
-/*************************/
-
-static int h263_find_frame_end(ParseContext1 *pc, const uint8_t *buf, int buf_size)
-{
- int vop_found, i;
- uint32_t state;
-
- vop_found= pc->frame_start_found;
- state= pc->state;
-
- i=0;
- if(!vop_found){
- for(i=0; i<buf_size; i++){
- state= (state<<8) | buf[i];
- if(state>>(32-22) == 0x20){
- i++;
- vop_found=1;
- break;
- }
- }
- }
-
- if(vop_found){
- for(; i<buf_size; i++){
- state= (state<<8) | buf[i];
- if(state>>(32-22) == 0x20){
- pc->frame_start_found=0;
- pc->state=-1;
- return i-3;
- }
- }
- }
- pc->frame_start_found= vop_found;
- pc->state= state;
-
- return END_NOT_FOUND;
-}
-
-static int h263_parse(AVCodecParserContext *s,
- AVCodecContext *avctx,
- uint8_t **poutbuf, int *poutbuf_size,
+static int mpeg4video_split(AVCodecContext *avctx,
const uint8_t *buf, int buf_size)
-{
- ParseContext1 *pc = s->priv_data;
- int next;
-
- next= h263_find_frame_end(pc, buf, buf_size);
-
- if (ff_combine_frame1(pc, next, (uint8_t **)&buf, &buf_size) < 0) {
- *poutbuf = NULL;
- *poutbuf_size = 0;
- return buf_size;
- }
-
- *poutbuf = (uint8_t *)buf;
- *poutbuf_size = buf_size;
- return next;
-}
-
-/*************************/
-
-/**
- * finds the end of the current frame in the bitstream.
- * @return the position of the first byte of the next frame, or -1
- */
-static int h264_find_frame_end(ParseContext1 *pc, const uint8_t *buf, int buf_size)
{
int i;
- uint32_t state;
-//printf("first %02X%02X%02X%02X\n", buf[0], buf[1],buf[2],buf[3]);
-// mb_addr= pc->mb_addr - 1;
- state= pc->state;
- //FIXME this will fail with slices
+ uint32_t state= -1;
+
for(i=0; i<buf_size; i++){
state= (state<<8) | buf[i];
- if((state&0xFFFFFF1F) == 0x101 || (state&0xFFFFFF1F) == 0x102 || (state&0xFFFFFF1F) == 0x105){
- if(pc->frame_start_found){
- pc->state=-1;
- pc->frame_start_found= 0;
- return i-3;
- }
- pc->frame_start_found= 1;
- }
- }
-
- pc->state= state;
- return END_NOT_FOUND;
-}
-
-static int h264_parse(AVCodecParserContext *s,
- AVCodecContext *avctx,
- uint8_t **poutbuf, int *poutbuf_size,
- const uint8_t *buf, int buf_size)
-{
- ParseContext1 *pc = s->priv_data;
- int next;
-
- next= h264_find_frame_end(pc, buf, buf_size);
-
- if (ff_combine_frame1(pc, next, (uint8_t **)&buf, &buf_size) < 0) {
- *poutbuf = NULL;
- *poutbuf_size = 0;
- return buf_size;
+ if(state == 0x1B3 || state == 0x1B6)
+ return i-3;
}
-
- *poutbuf = (uint8_t *)buf;
- *poutbuf_size = buf_size;
- return next;
+ return 0;
}
/*************************/
int frame_size;
int free_format_frame_size;
int free_format_next_header;
+ uint32_t header;
+ int header_count;
} MpegAudioParseContext;
#define MPA_HEADER_SIZE 4
/* header + layer + bitrate + freq + lsf/mpeg25 */
+#undef SAME_HEADER_MASK /* mpegaudio.h defines different version */
#define SAME_HEADER_MASK \
- (0xffe00000 | (3 << 17) | (0xf << 12) | (3 << 10) | (3 << 19))
+ (0xffe00000 | (3 << 17) | (3 << 10) | (3 << 19))
static int mpegaudio_parse_init(AVCodecParserContext *s1)
{
const uint8_t *buf, int buf_size)
{
MpegAudioParseContext *s = s1->priv_data;
- int len, ret;
+ int len, ret, sr;
uint32_t header;
const uint8_t *buf_ptr;
}
if ((s->inbuf_ptr - s->inbuf) >= MPA_HEADER_SIZE) {
got_header:
+ sr= avctx->sample_rate;
header = (s->inbuf[0] << 24) | (s->inbuf[1] << 16) |
(s->inbuf[2] << 8) | s->inbuf[3];
ret = mpa_decode_header(avctx, header);
if (ret < 0) {
+ s->header_count= -2;
/* no sync found : move by one byte (inefficient, but simple!) */
memmove(s->inbuf, s->inbuf + 1, s->inbuf_ptr - s->inbuf - 1);
s->inbuf_ptr--;
to get a new bitrate */
s->free_format_frame_size = 0;
} else {
+ if((header&SAME_HEADER_MASK) != (s->header&SAME_HEADER_MASK) && s->header)
+ s->header_count= -3;
+ s->header= header;
+ s->header_count++;
s->frame_size = ret;
+
#if 0
/* free format: prepare to compute frame size */
if (decode_header(s, header) == 1) {
}
#endif
}
+ if(s->header_count <= 0)
+ avctx->sample_rate= sr; //FIXME ugly
}
} else
#if 0
// next_data:
if (s->frame_size > 0 &&
(s->inbuf_ptr - s->inbuf) >= s->frame_size) {
- *poutbuf = s->inbuf;
- *poutbuf_size = s->inbuf_ptr - s->inbuf;
+ if(s->header_count > 0){
+ *poutbuf = s->inbuf;
+ *poutbuf_size = s->inbuf_ptr - s->inbuf;
+ }
s->inbuf_ptr = s->inbuf;
s->frame_size = 0;
break;
s->frame_size = len;
/* update codec info */
avctx->sample_rate = sample_rate;
- avctx->channels = ac3_channels[s->flags & 7];
- if (s->flags & A52_LFE)
- avctx->channels++;
+ /* set channels,except if the user explicitly requests 1 or 2 channels, XXX/FIXME this is a bit ugly */
+ if(avctx->channels!=1 && avctx->channels!=2){
+ avctx->channels = ac3_channels[s->flags & 7];
+ if (s->flags & A52_LFE)
+ avctx->channels++;
+ }
avctx->bit_rate = bit_rate;
avctx->frame_size = 6 * 256;
}
sizeof(ParseContext1),
NULL,
mpegvideo_parse,
- mpegvideo_parse_close,
+ parse1_close,
+ mpegvideo_split,
};
AVCodecParser mpeg4video_parser = {
sizeof(ParseContext1),
mpeg4video_parse_init,
mpeg4video_parse,
- mpegvideo_parse_close,
-};
-
-AVCodecParser h263_parser = {
- { CODEC_ID_H263 },
- sizeof(ParseContext1),
- NULL,
- h263_parse,
- mpegvideo_parse_close,
-};
-
-AVCodecParser h264_parser = {
- { CODEC_ID_H264 },
- sizeof(ParseContext1),
- NULL,
- h264_parse,
- mpegvideo_parse_close,
+ parse1_close,
+ mpeg4video_split,
};
AVCodecParser mpegaudio_parser = {