简析H264编码中的GOP

1.什么是GOP

GOP即Group of Pictures,意思是画面组,一个GOP就是一组连续的画面。

2.实际例子

假设有一个视频,每秒25帧,帧与帧之间的间隔为40ms,那如果10分钟总的帧数就是25*60*10,如此多的帧在实际压缩的时候就非常困难,GOP的处理方式就是将这些帧进行分组。

分组按照帧的相关性进行,例如视频中人物主要有看望远镜和敲键盘两个动作,就可以把他们分为两组,看望远镜的为一组,敲键盘的为一组。虽然看望远镜的帧观看的视角会不一样,敲键盘也有抬起和按下不同的动作,但是每个组中帧的大部分内容都是相同的。一个group其实就是描述一个图像目标的细微差别,在同一个组中的视频帧是强相关的,不同组中的帧则相关性非常小。

由于GOP中帧与帧的差别特别小,在进行编码压缩的时候,数据量就小了很多。比如上面看望远镜的那一组,每一帧的背景是一样的,只是看望远镜的姿势、角度不同,在进行计算的时候完全可以把他们的背景用一张图表示。看望远镜的人物也是有相同部分的,比如每一帧中的头发是几乎一样的,只是身体略有不同,望远镜的角度略有不同,在计算的时候我们只需要将这些差值进行存储。由此,可以发现,每一组GOP只需要存很少的数据,就可以将所有帧还原回来。虽然不是100%还原,因为H264本来就是有损压缩。

S32 record_init(void) { LENS_MASK_INFO lens_mask_info = {0}; sd_snapshot_jpeg_stream_start(); g_record = (record_t*)calloc(1, sizeof(record_t)); if (NULL == g_record) { STM_ERROR("g_record malloc failed"); goto err_exit; } pthread_mutex_init(&g_record->status_mutex, NULL); pthread_cond_init(&g_record->status_cond, NULL); pthread_mutex_init(&g_record->video_gop_mutex, NULL); pthread_cond_init(&g_record->video_gop_cond, NULL); pthread_mutex_init(&g_record->audio_gop_mutex, NULL); pthread_cond_init(&g_record->audio_gop_cond, NULL); pthread_mutex_init(&g_record->thread_mutex, NULL); pthread_cond_init(&g_record->thread_cond, NULL); g_record->type = AVDM_TYPE_MAIN; g_record->call_type = AVDM_TYPE_VIDEO_CALL; #ifdef DUAL_CAM g_record->video2_type = AVDM_TYPE_MAIN2; #endif g_record->stm_fd = -1; g_record->pid = 0; g_record->thread_state = THREAD_STATE_STOPPED; g_record->rec_status = REC_STAT_PRE; g_record->delay_timer_id = -1; // g_record->inited = FALSE; /* calloc已经为FALSE */ /* 设置事件延录时间:60s */ Event_SetDelayTime(60); if (SnapshotIndexMod_Init() != 0) { STM_ERROR("SnapshotIndexMod_Init() fail."); } /* 获取镜头遮蔽状态 */ if (0 != ds_read(LENS_MASK_INFO_PATH, &lens_mask_info, sizeof(LENS_MASK_INFO))) { g_record->lens_mask_enabled = lens_mask_info.enabled; } else { STM_WARN("record get lens mask info failed."); g_record->lens_mask_enabled = FALSE; } #ifdef HUB_MANAGE_SUPPORT HUB_MANAGE_STORAGE_INFO storage_info = {0}; ds_read(HUB_MANAGE_STORAGE_INFO_PATH, &storage_info, sizeof(HUB_MANAGE_STORAGE_INFO)); g_hub_storage_enabled = storage_info.enabled; #endif load_rectime_restriction_cfg(); load_time_jump_threshold_cfg(); reload_record_adv_config(); reload_record_audio_config(); ds_update_sd_available_info(); /* 初始化录像事件参数 */ if (ERROR == rec_chn_init()) { STM_ERROR("record operate rec chn init failed"); goto err_exit; } if (ERROR == rec_disk_info_init()) { STM_ERROR("record disk info init failed"); goto err_exit; } if (ERROR == avdm_register_block_callback(g_record->type, record_avdm_cb, NULL)) { STM_ERROR("record register avdm video block callback failed"); goto err_exit; } #ifdef DUAL_CAM if (ERROR == avdm_register_block_callback(g_record->video2_type, record_avdm_video2_cb, NULL)) { STM_ERROR("record register avdm video2 block callback failed"); goto err_exit; } #endif if (ERROR == avdm_register_block_callback(AVDM_TYPE_AUDIO, record_avdm_audio_cb, NULL)) { STM_ERROR("record register avdm audio block callback failed"); goto err_exit; } if (0 != pthread_create(&g_record->pid, NULL, record_thread_func, NULL)) { STM_ERROR("pthread_create record thread func failed"); g_record->thread_state = THREAD_STATE_FINISHED; goto err_exit; } g_record->stm_fd = stm_open(0, STORAGE_TYPE_VIDEO, F_MUX_MPEGPS, STM_MODE_WR); if (g_record->stm_fd == -1) { STM_ERROR("storage is not prepared for writing"); goto err_exit; } if (ERROR == msg_attach_handler(REC_PLAN_ACTION_CHANGED, record_plan_action_callback)) { STM_ERROR("record plan event msg handler attached failed"); goto err_exit; } if (ERROR == msg_attach_handler(EVENT_CHANGE_MID, event_change_callback)) { STM_ERROR("event_change msg handler attached failed"); goto err_exit; } /* 关注镜头遮蔽消息 */ if (ERROR == msg_attach_handler(COVER_LENS_MASK_RELOAD, record_lens_mask_callback)) { STM_ERROR("record lens mask event msg handler attached failed."); goto err_exit; } if (ERROR == msg_attach_handler(MSGID_DMS_CMD, record_call_handle)) { STM_ERROR("record dms cmd handle attached failed."); goto err_exit; } /* 关注侦测事件推送消息 */ if (ERROR == msg_attach_handler(EVENT_PUSH_MSG_MID, event_push_callback)) { STM_ERROR("event push msg handler attached failed."); goto err_exit; } #ifdef HUB_MANAGE_SUPPORT if (ERROR == msg_attach_handler(HUB_STREAM_RECORD_BACK_MSG_ID, hub_record_fallback_handle)) { STM_ERROR("hub_connection_state handle attached failed."); goto err_exit; } #endif g_record->inited = TRUE; g_record->need_update_index = FALSE; STM_DEBUG("record init over"); return OK; err_exit: record_exit(); return ERROR; }这里是初始化?其中我想添加在录像线程中加入一个对讲通话的录像,那需要注册关于video_call的东西吗?因为录像的时候不一定有video_call啊,平时只有普通video(主摄)?
10-22
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值