void X264Encoder::FindSpsAndPPsFromBuf(const char* dataBuf, int bufLen) { char* tmp_buf = new char[5*1024*1024]; int tmp_len = 0; ff_avc_parse_nal_units(dataBuf, bufLen, tmp_buf, &tmp_len); char* start = tmp_buf; char* end = tmp_buf + tmp_len; /* look for sps and pps */ while (start < end) { unsigned int size = BytesToUI32(start); unsigned char nal_type = start[4] & 0x1f; if (nal_type == 7) /* SPS */ { sps_size_ = size; sps_ = (char*)malloc(sps_size_); memcpy(sps_, start + 4, sps_size_); } else if (nal_type == 8) /* PPS */ { pps_size_ = size; pps_ = (char*)malloc(pps_size_); memcpy(pps_, start + 4, pps_size_); } start += size + 4; } delete[] tmp_buf; }
int ff_isom_write_avcc(ByteIOContext *pb, const uint8_t *data, int len) { if (len > 6) { /* check for h264 start code */ if (AV_RB32(data) == 0x00000001) { uint8_t *buf=NULL, *end, *start; uint32_t sps_size=0, pps_size=0; uint8_t *sps=0, *pps=0; int ret = ff_avc_parse_nal_units(data, &buf, &len); if (ret < 0) return ret; start = buf; end = buf + len; /* look for sps and pps */ while (buf < end) { unsigned int size; uint8_t nal_type; size = AV_RB32(buf); nal_type = buf[4] & 0x1f; if (nal_type == 7) { /* SPS */ sps = buf + 4; sps_size = size; } else if (nal_type == 8) { /* PPS */ pps = buf + 4; pps_size = size; } buf += size + 4; } assert(sps); assert(pps); put_byte(pb, 1); /* version */ put_byte(pb, sps[1]); /* profile */ put_byte(pb, sps[2]); /* profile compat */ put_byte(pb, sps[3]); /* level */ put_byte(pb, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */ put_byte(pb, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */ put_be16(pb, sps_size); put_buffer(pb, sps, sps_size); put_byte(pb, 1); /* number of pps */ put_be16(pb, pps_size); put_buffer(pb, pps, pps_size); av_free(start); } else { put_buffer(pb, data, len); } } return 0; }
int ff_avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size) { AVIOContext *pb; int ret = avio_open_dyn_buf(&pb); if(ret < 0) return ret; ff_avc_parse_nal_units(pb, buf_in, *size); av_freep(buf); *size = avio_close_dyn_buf(pb, buf); return 0; }
static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) { ByteIOContext *pb = s->pb; AVCodecContext *enc = s->streams[pkt->stream_index]->codec; FLVContext *flv = s->priv_data; unsigned ts; int size= pkt->size; int flags, flags_size; // av_log(s, AV_LOG_DEBUG, "type:%d pts: %"PRId64" size:%d\n", enc->codec_type, timestamp, size); if(enc->codec_id == CODEC_ID_VP6 || enc->codec_id == CODEC_ID_VP6F || enc->codec_id == CODEC_ID_AAC) flags_size= 2; else if(enc->codec_id == CODEC_ID_H264) flags_size= 5; else flags_size= 1; if (enc->codec_type == CODEC_TYPE_VIDEO) { put_byte(pb, FLV_TAG_TYPE_VIDEO); flags = enc->codec_tag; if(flags == 0) { av_log(enc, AV_LOG_ERROR, "video codec %X not compatible with flv\n",enc->codec_id); return -1; } flags |= pkt->flags & PKT_FLAG_KEY ? FLV_FRAME_KEY : FLV_FRAME_INTER; } else { assert(enc->codec_type == CODEC_TYPE_AUDIO); flags = get_audio_flags(enc); assert(size); put_byte(pb, FLV_TAG_TYPE_AUDIO); } if (enc->codec_id == CODEC_ID_H264 && /* check if extradata looks like mp4 formated */ enc->extradata_size > 0 && *(uint8_t*)enc->extradata != 1) { if (ff_avc_parse_nal_units(pkt->data, &pkt->data, &pkt->size) < 0) return -1; assert(pkt->size); size = pkt->size; /* cast needed to get negative value */ if (!flv->delay && (int32_t)pkt->dts < 0) flv->delay = -(int32_t)pkt->dts; } ts = pkt->dts + flv->delay; // add delay to force positive dts put_be24(pb,size + flags_size); put_be24(pb,ts); put_byte(pb,ts >> 24); put_be24(pb,flv->reserved); put_byte(pb,flags); if (enc->codec_id == CODEC_ID_VP6) put_byte(pb,0); if (enc->codec_id == CODEC_ID_VP6F) put_byte(pb, enc->extradata_size ? enc->extradata[0] : 0); else if (enc->codec_id == CODEC_ID_AAC) put_byte(pb,1); // AAC raw else if (enc->codec_id == CODEC_ID_H264) { put_byte(pb,1); // AVC NALU put_be24(pb,pkt->pts - (int32_t)pkt->dts); } put_buffer(pb, pkt->data, size); put_be32(pb,size+flags_size+11); // previous tag size flv->duration = FFMAX(flv->duration, pkt->pts + flv->delay + pkt->duration); put_flush_packet(pb); return 0; }